Skip to content

Commit 8dec8c0

Browse files
committed
add context options for background GC
1 parent b19f85c commit 8dec8c0

File tree

2 files changed

+34
-18
lines changed

2 files changed

+34
-18
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiContext.java

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,9 @@ private static final class BackgroundGCTask implements Runnable {
607607

608608
private BackgroundGCTask(PythonContext context) {
609609
this.ctx = new WeakReference<>(context);
610+
this.rssInterval = context.getOption(PythonOptions.BackgroundGCTaskInterval);
611+
this.gcRSSThreshold = context.getOption(PythonOptions.BackgroundGCTaskThreshold) / (double) 100;
612+
this.gcRSSMinimum = context.getOption(PythonOptions.BackgroundGCTaskMinimum);
610613
}
611614

612615
Object nativeSymbol = null;
@@ -619,26 +622,26 @@ private BackgroundGCTask(PythonContext context) {
619622
final WeakReference<PythonContext> ctx;
620623

621624
// RSS monitor interval in ms
622-
static final int RSS_INTERVAL = Integer.getInteger("python.RSSInterval", 1000);
625+
final int rssInterval;
623626
/**
624627
* RSS percentage increase between System.gc() calls. Low percentage will trigger
625628
* System.gc() more often which can cause unnecessary overhead.
626629
*
627630
* <ul>
628-
* why 30%? it's purely based on the {@code huggingface} example.
631+
* Based on the {@code huggingface} example:
629632
* <li>less than 30%: max RSS ~22GB (>200 second per iteration)</li>
630633
* <li>30%: max RSS ~24GB (~150 second per iteration)</li>
631634
* <li>larger than 30%: max RSS ~38GB (~140 second per iteration)</li>
632635
* </ul>
633636
*
634637
* <pre>
635638
*/
636-
static final double GC_RSS_THRESHOLD = Integer.getInteger("python.RSSThreshold", 30) / 100.0;
639+
final double gcRSSThreshold;
637640

638641
/**
639642
* RSS minimum memory (in megabytes) start calling System.gc(). Default is 4GB.
640643
*/
641-
static final double GC_RSS_MINIMUM = Integer.getInteger("python.RSSMinimumMB", 4096);
644+
final double gcRSSMinimum;
642645

643646
Long getCurrentRSS() {
644647
if (nativeSymbol == null) {
@@ -657,7 +660,7 @@ Long getCurrentRSS() {
657660
public void run() {
658661
try {
659662
while (true) {
660-
Thread.sleep(RSS_INTERVAL);
663+
Thread.sleep(rssInterval);
661664
perform();
662665
}
663666
} catch (InterruptedException e) {
@@ -685,7 +688,7 @@ private void perform() {
685688
return;
686689
}
687690

688-
if (rss < GC_RSS_MINIMUM) {
691+
if (rss < gcRSSMinimum) {
689692
return;
690693
}
691694

@@ -697,15 +700,15 @@ private void perform() {
697700
}
698701

699702
double ratio = ((rss - this.previousRSS) / (double) this.previousRSS);
700-
if (ratio >= GC_RSS_THRESHOLD) {
703+
if (ratio >= gcRSSThreshold) {
701704
this.previousWeakrefCount = currentWeakrefCount;
702705

703706
long start = System.nanoTime();
704707
PythonUtils.forceFullGC();
705708
long gcTime = (System.nanoTime() - start) / 1000000;
706709

707710
if (LOGGER.isLoggable(Level.FINER)) {
708-
LOGGER.finer(PythonUtils.formatJString("Background GC Task -- GC [%d ms] RSS [%d MB]->[%d MB](%.1f%%)",
711+
LOGGER.info(PythonUtils.formatJString("Background GC Task -- GC [%d ms] RSS [%d MB]->[%d MB](%.1f%%)",
709712
gcTime, previousRSS, rss, ratio * 100));
710713
}
711714
/*
@@ -719,7 +722,7 @@ private void perform() {
719722
* mappings (RssFile) and shmem memory (RssShmem). GC can only reduce RssAnon while
720723
* RssFile is managed by the operating system which doesn't go down easily.
721724
*/
722-
this.previousRSS += (long) (this.previousRSS * GC_RSS_THRESHOLD);
725+
this.previousRSS += (long) (this.previousRSS * gcRSSThreshold);
723726
}
724727
}
725728
}
@@ -731,7 +734,7 @@ public long getCurrentRSS() {
731734
if (rss == -1) {
732735
try {
733736
// in case it just started
734-
Thread.sleep(BackgroundGCTask.RSS_INTERVAL);
737+
Thread.sleep(gcTask.rssInterval);
735738
} catch (InterruptedException e) {
736739
Thread.currentThread().interrupt();
737740
}
@@ -745,15 +748,16 @@ public long getCurrentRSS() {
745748
@SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH") // context.get() is never null here
746749
void runBackgroundGCTask(PythonContext context) {
747750
CompilerAsserts.neverPartOfCompilation();
748-
if (ImageInfo.inImageBuildtimeCode() || context.getOption(PythonOptions.NoAsyncActions)) {
751+
if (ImageInfo.inImageBuildtimeCode() //
752+
|| context.getOption(PythonOptions.NoAsyncActions) //
753+
|| !PythonOptions.AUTOMATIC_ASYNC_ACTIONS //
754+
|| !context.getOption(PythonOptions.BackgroundGCTask)) {
749755
return;
750756
}
751-
if (PythonOptions.AUTOMATIC_ASYNC_ACTIONS) {
752-
backgroundGCTaskThread = context.getEnv().newTruffleThreadBuilder(gcTask).context(context.getEnv().getContext()).build();
753-
backgroundGCTaskThread.setDaemon(true);
754-
backgroundGCTaskThread.setName("python-gc-task");
755-
backgroundGCTaskThread.start();
756-
}
757+
backgroundGCTaskThread = context.getEnv().newTruffleThreadBuilder(gcTask).context(context.getEnv().getContext()).build();
758+
backgroundGCTaskThread.setDaemon(true);
759+
backgroundGCTaskThread.setName("python-gc-task");
760+
backgroundGCTaskThread.start();
757761
}
758762

759763
/**

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonOptions.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
import java.util.Map;
4545
import java.util.Optional;
4646

47-
import com.oracle.truffle.api.exception.AbstractTruffleException;
4847
import org.graalvm.options.OptionCategory;
4948
import org.graalvm.options.OptionDescriptor;
5049
import org.graalvm.options.OptionDescriptors;
@@ -64,6 +63,7 @@
6463
import com.oracle.truffle.api.Option;
6564
import com.oracle.truffle.api.TruffleLanguage.Env;
6665
import com.oracle.truffle.api.dsl.Idempotent;
66+
import com.oracle.truffle.api.exception.AbstractTruffleException;
6767
import com.oracle.truffle.api.nodes.ExplodeLoop;
6868
import com.oracle.truffle.api.strings.TruffleString;
6969

@@ -354,6 +354,18 @@ private PythonOptions() {
354354
@Option(category = OptionCategory.EXPERT, usageSyntax = "true|false", help = "Whether the Python GC should be enabled (default) or not.") //
355355
public static final OptionKey<Boolean> PythonGC = new OptionKey<>(true);
356356

357+
@Option(category = OptionCategory.INTERNAL, usageSyntax = "true|false", help = "Whether the background GC task should be enabled (default) or not.") //
358+
public static final OptionKey<Boolean> BackgroundGCTask = new OptionKey<>(true);
359+
360+
@Option(category = OptionCategory.INTERNAL, usageSyntax = "<time>", help = "Specifies the interval (ms) for the background GC task to monitor the resident set size (RSS)") //
361+
public static final OptionKey<Integer> BackgroundGCTaskInterval = new OptionKey<>(1000);
362+
363+
@Option(category = OptionCategory.INTERNAL, usageSyntax = "<limit>", help = "The percentage increase in RSS memory between System.gc() calls. Low percentage will trigger System.gc() more often. (default: 30).") //
364+
public static final OptionKey<Integer> BackgroundGCTaskThreshold = new OptionKey<>(30);
365+
366+
@Option(category = OptionCategory.INTERNAL, usageSyntax = "<megabytes>", help = "The minimum RSS memory (in megabytes) to start calling System.gc(). (default: 4 GB).") //
367+
public static final OptionKey<Integer> BackgroundGCTaskMinimum = new OptionKey<>(4096);
368+
357369
@EngineOption @Option(category = OptionCategory.USER, usageSyntax = "true|false", help = "Emulate some Jython features that can cause performance degradation", stability = OptionStability.STABLE) //
358370
public static final OptionKey<Boolean> EmulateJython = new OptionKey<>(false);
359371

0 commit comments

Comments
 (0)