From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS6939 216.218.128.0/17 X-Spam-Status: No, score=-0.9 required=3.0 tests=AWL,BAYES_00, RCVD_IN_MSPIKE_BL,RCVD_IN_MSPIKE_ZBI,RCVD_IN_XBL,RDNS_NONE,SPF_FAIL, SPF_HELO_FAIL,TO_EQ_FM_DOM_SPF_FAIL shortcircuit=no autolearn=no autolearn_force=no version=3.4.0 Received: from 80x24.org (unknown [216.218.222.12]) by dcvr.yhbt.net (Postfix) with ESMTP id B71981F406 for ; Mon, 14 May 2018 20:15:11 +0000 (UTC) From: Eric Wong To: spew@80x24.org Subject: [PATCH] gc.c: enter sleepy GC start Date: Mon, 14 May 2018 20:15:09 +0000 Message-Id: <20180514201509.28069-1-e@80x24.org> List-Id: For rare situations when no free pages are available, we may start GC. This is a conservative change which may not be worth the effort. In the future, we may prematurely start GC before pages become unavailable. --- gc.c | 27 +++++++++++++++++++++++++-- gc.h | 7 +++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/gc.c b/gc.c index c705d0d513..c7f19a5f81 100644 --- a/gc.c +++ b/gc.c @@ -352,6 +352,7 @@ typedef enum { GPR_FLAG_METHOD = 0x400, GPR_FLAG_CAPI = 0x800, GPR_FLAG_STRESS = 0x1000, + GPR_FLAG_SLEEPY = 0x8000, /* others */ GPR_FLAG_IMMEDIATE_SWEEP = 0x2000, @@ -6536,7 +6537,23 @@ gc_rest(rb_objspace_t *objspace) } } -#if RUBY_GC_SLEEPY_SWEEP || RUBY_GC_SLEEPY_MARK +#if RUBY_GC_SLEEPY_SWEEP || RUBY_GC_SLEEPY_MARK || RUBY_GC_SLEEPY_START +static inline int +can_sleepy_start(rb_objspace_t *objspace) +{ + rb_heap_t *heap = heap_eden; + + if (!RUBY_GC_SLEEPY_START || dont_gc || during_gc || ruby_disable_gc) { + return 0; + } + if (heap->free_pages == NULL && + (will_be_incremental_marking(objspace) || + heap_increment(objspace, heap) == FALSE)) { + return 1; + } + return 0; +} + /* this is just a hint, TOCTOU race may happen */ int rb_gc_inprogress(const rb_execution_context_t *ec) @@ -6544,7 +6561,8 @@ rb_gc_inprogress(const rb_execution_context_t *ec) rb_objspace_t *objspace = rb_ec_vm_ptr(ec)->objspace; return (RUBY_GC_SLEEPY_SWEEP && is_lazy_sweeping(&objspace->eden_heap)) || - (RUBY_GC_SLEEPY_MARK && is_incremental_marking(objspace)); + (RUBY_GC_SLEEPY_MARK && is_incremental_marking(objspace) || + can_sleepy_start(objspace)); } /* returns true if there is more work to do, false if not */ @@ -6563,6 +6581,9 @@ rb_gc_step(const rb_execution_context_t *ec) gc_marks_continue(objspace, &objspace->eden_heap); #endif } + else if (can_sleepy_start(objspace)) { + gc_start(objspace, FALSE, FALSE, FALSE, GPR_FLAG_SLEEPY); + } return rb_gc_inprogress(ec); } @@ -6842,6 +6863,7 @@ gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const int orig_ { static VALUE sym_major_by = Qnil, sym_gc_by, sym_immediate_sweep, sym_have_finalizer, sym_state; static VALUE sym_nofree, sym_oldgen, sym_shady, sym_force, sym_stress; + static VALUE sym_sleepy; #if RGENGC_ESTIMATE_OLDMALLOC static VALUE sym_oldmalloc; #endif @@ -6911,6 +6933,7 @@ gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const int orig_ (flags & GPR_FLAG_METHOD) ? sym_method : (flags & GPR_FLAG_CAPI) ? sym_capi : (flags & GPR_FLAG_STRESS) ? sym_stress : + (flags & GPR_FLAG_SLEEPY) ? sym_sleepy : Qnil ); diff --git a/gc.h b/gc.h index 1f8a06cdc7..954fa86162 100644 --- a/gc.h +++ b/gc.h @@ -99,11 +99,14 @@ struct rb_execution_context_struct; #ifndef RUBY_GC_SLEEPY_MARK # define RUBY_GC_SLEEPY_MARK 1 #endif +#ifndef RUBY_GC_SLEEPY_START +# define RUBY_GC_SLEEPY_START 1 +#endif -#if RUBY_GC_SLEEPY_SWEEP || RUBY_GC_SLEEPY_MARK +#if RUBY_GC_SLEEPY_SWEEP || RUBY_GC_SLEEPY_MARK || RUBY_GC_SLEEPY_START int rb_gc_inprogress(const struct rb_execution_context_struct *); int rb_gc_step(const struct rb_execution_context_struct *); -#else /* (RUBY_GC_SLEEPY_SWEEP|RUBY_GC_SLEEPY_MARK) == 0 */ +#else /* (RUBY_GC_SLEEPY_SWEEP|RUBY_GC_SLEEPY_MARK|RUBY_GC_SLEEPY_START) == 0 */ static inline int rb_gc_inprogress(const struct rb_execution_context_struct *ec) { -- EW