You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently we use a usleep(100) loop in getfull to "pause" when we're waiting for GC work during STW mark termination. This both wastes CPU and increases STW latency. It has also caused several problems on platforms where 100us sleeps don't work well: it used to require us to raise the system-wide timer resolution on Windows (#8687), and on Unix platforms without high-resolution timers (older Linux on ARM, OpenBSD, and Solaris), this actually gives up the entire rest of the time slice and seriously interferes with profiling signals (#13405).
We should replace this with a more explicit synchronization mechanism. Conveniently, because getfull is only ever used during STW, this synchronization doesn't have to involve anything beyond getfull and putfull. There are two wake-up conditions that, together, are sufficient: a new buffer is added to the full list, or work.nproc == work.nwait. The former case only happens in putfull. Ideally we can sharpen that to "a new buffer is added to the full list and there's a blocked getfull" without introducing races. The latter case requires waking all blocked getfulls, so we have to be careful to not race with another getfull blocking. However, we do know that if work.nproc == work.nwait, some non-blocked getfull will have detected that condition, so it can trigger the global wake up.
Commit ee3d201 essentially fixed this. The sleep is still there, but at this point the only time we ever call getfull is in a fallback path of STW mark termination when a rare race happens that causes mark termination to start early (see the commit for more details). I plan to fix this race in Go 1.9, which will actually eliminate getfull and the sleep, but for all practical purposes, this is now fixed.
Currently we use a usleep(100) loop in getfull to "pause" when we're waiting for GC work during STW mark termination. This both wastes CPU and increases STW latency. It has also caused several problems on platforms where 100us sleeps don't work well: it used to require us to raise the system-wide timer resolution on Windows (#8687), and on Unix platforms without high-resolution timers (older Linux on ARM, OpenBSD, and Solaris), this actually gives up the entire rest of the time slice and seriously interferes with profiling signals (#13405).
We should replace this with a more explicit synchronization mechanism. Conveniently, because getfull is only ever used during STW, this synchronization doesn't have to involve anything beyond getfull and putfull. There are two wake-up conditions that, together, are sufficient: a new buffer is added to the full list, or work.nproc == work.nwait. The former case only happens in putfull. Ideally we can sharpen that to "a new buffer is added to the full list and there's a blocked getfull" without introducing races. The latter case requires waking all blocked getfulls, so we have to be careful to not race with another getfull blocking. However, we do know that if work.nproc == work.nwait, some non-blocked getfull will have detected that condition, so it can trigger the global wake up.
/cc @RLH
The text was updated successfully, but these errors were encountered: