summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2018-04-14 06:18:49 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2018-04-14 06:18:49 +0900
commitfabc460880fbabd18369a7ef8715538c83ebffc9 (patch)
tree4239c6374dc719f7049524d55b09fd3fe0cdfbe7 /src
parent3b273243e6ad4eaae7fcb7886eb168894aaf513a (diff)
downloadmruby-fabc460880fbabd18369a7ef8715538c83ebffc9.tar.gz
mruby-fabc460880fbabd18369a7ef8715538c83ebffc9.zip
Invoke full GC when too many objects allocated during GC; fix #3998
When object allocation rate during incremental GC is too high, the `gc->majorgc_old_threshold` becomes too big. This means major GC start slower and old objects stay longer (and consume too much memory).
Diffstat (limited to 'src')
-rw-r--r--src/gc.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/src/gc.c b/src/gc.c
index 6f3aef8a7..631f7b910 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -345,6 +345,7 @@ add_heap(mrb_state *mrb, mrb_gc *gc)
#define DEFAULT_GC_INTERVAL_RATIO 200
#define DEFAULT_GC_STEP_RATIO 200
#define MAJOR_GC_INC_RATIO 120
+#define MAJOR_GC_TOOMANY 10000
#define is_generational(gc) ((gc)->generational)
#define is_major_gc(gc) (is_generational(gc) && (gc)->full)
#define is_minor_gc(gc) (is_generational(gc) && !(gc)->full)
@@ -1209,7 +1210,13 @@ mrb_incremental_gc(mrb_state *mrb)
}
if (is_major_gc(gc)) {
- gc->majorgc_old_threshold = gc->live_after_mark/100 * MAJOR_GC_INC_RATIO;
+ size_t threshold = gc->live_after_mark/100 * MAJOR_GC_INC_RATIO;
+
+ if (threshold > MAJOR_GC_TOOMANY) {
+ mrb_full_gc(mrb);
+ threshold = gc->live_after_mark/100 * MAJOR_GC_INC_RATIO;
+ }
+ gc->majorgc_old_threshold = threshold;
gc->full = FALSE;
}
else if (is_minor_gc(gc)) {