From: Koichi Sasada Date: 2018-05-02T12:43:50+09:00 Subject: [ruby-core:86816] Re: [Ruby trunk Feature#14723] [WIP] sleepy GC On 2018/05/02 11:49, Eric Wong wrote: > I fetch and run "git diff" locally which gives me many options > > REMOTE=80x24 > git remote add $REMOTE git://80x24.org/ruby.git > git fetch $REMOTE > git diff $OLD $NEW > > $OLD and $NEW are commits which "git request-pull" outputs in my previous > emails: > > > The following changes since commit $OLD > > > > $OLD_SUBJECT > > > > are available in the Git repository at: > > > > git://80x24.org/ruby.git BRANCH > > > > for you to fetch changes up to $NEW > > You can also: > > curl https://80x24.org/spew/20180501080844.22751-2-e@80x24.org/raw \ > https://80x24.org/spew/20180501080844.22751-3-e@80x24.org/raw \ > https://80x24.org/spew/20180501080844.22751-4-e@80x24.org/raw \ > https://80x24.org/spew/20180501080844.22751-5-e@80x24.org/raw \ > | git am > > (I run scripts from my $EDITOR and mail client, of course :) Great. Thank you! >>> +rb_gc_step(const rb_execution_context_t *ec) >> >> How about to add assertion that rb_gc_inprogress() returns true? > > I don't think that's safe. For native_sleep callers; we release > GVL after calling rb_gc_step; so sometimes rb_gc_step becomes > a no-op (because other thread took GVL and did GC). OK. I assumed that this "step" API is used with "rb_gc_inprogress()". But it is not correct. >> https://80x24.org/spew/20180501080844.22751-5-e@80x24.org/raw >> >>> @@ -288,8 +294,17 @@ rb_mutex_lock(VALUE self) >> >> I can't understand why GC at acquiring (and restarting) timing is needed. >> Why? >> >> For other functions, I have a same question.happen. > > For mutex_lock, it only does GC if it can't acquire immediately. > Since mutex_lock cannot proceed, it can probably do GC. ``` + if (mutex->th == th) { + mutex_locked(th, self); + } + if (do_gc) { + /* + * Likely no point in checking for GVL contention here + * this Mutex is already contended and we just yielded + * above. + */ + do_gc = rb_gc_step(th->ec); + } ``` it should be `else if (do_gc)`, isn't? > One problem I have now is threads in THREAD_STOPPED_FOREVER > state cannot continuously perform GC if some other thread > is constantly making garbage and never sleeping. > nr = 100_000 > th = Thread.new do > File.open('/dev/urandom') do |rd| > nr.times { rd.read(16384) } > end > end > > # no improvement, since it enters sleep and stays there > th.join > > # instead, this works (but wastes battery if there's no garbage) > true until th.join(0.01) I'm not sure why it is a problem. Created thread do `read` and it can GC incrementally, or if `read` return immediately, there are no need to step more GC (usual GC should be enough), especially for throughput. > So maybe we add heuristics for entering sleep for methods in > thread.c and thread_sync.c and possibly continuing to schedule > threads in THREAD_STOPPED_FOREVER state to enable them to > perform cleanup. I don't think this is urgent, and we can > ignore this case for now. "cleanup"? do GC steps? I agree on them (requirements and immediacy). -- // SASADA Koichi at atdot dot net Unsubscribe: