# Pardon the interruption: Loop preemption in Go 1.14 迭代点: - 1.5 - concurrent garbage collector - 1.6 - concurrent finalizer scans - dirty stack tracking - global write barriers - 1.7 - concurrent stack shrinking - 1.8 - hybrid write barrier 抢占: - 1.0 - voluntary preemption only - 1.2 - function call preemption - function entry -> grow stack/preempt -> Y -> call runtime - 1.4 - asynchronous preemption - +0.3% binary size - 0 performance overhead - ~25us typical preemption bound 一些技术尝试: - preempt back-edges - adding instructions to loops isn't viable - 每次loop判断preempt - 8% slowdown - "fowward simulation" - use signals, like an OS kernal - zero overhead, but doesn't work with GC - 一次切换寄存器地址变了 - signals + gc stack maps at every instruction - +10% binary size - stack maps everywhere bloats binaries and doesn't "keep it simple" - **signal-based preemption with conservative innermost frame scanning** - 1.14 - 实现 - send a signal to the goroutine - 23 SIGURG - examine where it stopped/conservative scanning/precisely scanning - `runtime.asyncPreempt` - requires `non-moving GC` - https://en.wikipedia.org/wiki/Tracing_garbage_collection#Moving_vs._non-moving