From fef89d9a9e8d979417eaf7429a6668125420e000 Mon Sep 17 00:00:00 2001 From: joeblew999 Date: Fri, 2 Oct 2026 19:49:12 +0700 Subject: [PATCH] runtime: build tag runtime_nofinalizerpressure turns off the finalizer pressure GC The scheduler runs a full collection whenever it goes idle and finalizerGCThreshold finalizers were registered since the last one. A syscall/js program registers a finalizer for every js.Value and goes idle at every await, so it collects at nearly every pause: 100 collections in 100 event-loop turns in the reproduction in #5800. The threshold already means 'off' when it is zero. This moves the constant into two files so that -tags=runtime_nofinalizerpressure selects zero. The default is unchanged. Updates #5800 --- src/runtime/gc_finalizer.go | 4 ---- src/runtime/gc_finalizer_nopressure.go | 10 ++++++++++ src/runtime/gc_finalizer_pressure.go | 7 +++++++ 3 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 src/runtime/gc_finalizer_nopressure.go create mode 100644 src/runtime/gc_finalizer_pressure.go diff --git a/src/runtime/gc_finalizer.go b/src/runtime/gc_finalizer.go index df3a4c6c6f..62b4c20b62 100644 --- a/src/runtime/gc_finalizer.go +++ b/src/runtime/gc_finalizer.go @@ -33,10 +33,6 @@ type finalizerEntry struct { fn interface{} } -// finalizerGCThreshold starts pressure GC when registrations indicate external memory pressure. -// Larger tables use a proportional threshold. Zero disables this trigger. -const finalizerGCThreshold = 32 - var ( finalizers *finalizerEntry // registered finalizers; a GC root that keeps fn values alive finalizerPending *finalizerEntry // finalizers whose object died, waiting to run diff --git a/src/runtime/gc_finalizer_nopressure.go b/src/runtime/gc_finalizer_nopressure.go new file mode 100644 index 0000000000..56bd424a07 --- /dev/null +++ b/src/runtime/gc_finalizer_nopressure.go @@ -0,0 +1,10 @@ +//go:build (gc.conservative || gc.precise) && runtime_nofinalizerpressure + +package runtime + +// finalizerGCThreshold is zero with the build tag runtime_nofinalizerpressure: +// finalizer registrations do not start a collection, and finalizers run after +// the collections the heap itself needs. For programs that register many +// finalizers and go idle often, such as syscall/js programs, where every +// js.Value registers one and every await is an idle. +const finalizerGCThreshold = 0 diff --git a/src/runtime/gc_finalizer_pressure.go b/src/runtime/gc_finalizer_pressure.go new file mode 100644 index 0000000000..500464681f --- /dev/null +++ b/src/runtime/gc_finalizer_pressure.go @@ -0,0 +1,7 @@ +//go:build (gc.conservative || gc.precise) && !runtime_nofinalizerpressure + +package runtime + +// finalizerGCThreshold starts pressure GC when registrations indicate external memory pressure. +// Larger tables use a proportional threshold. Zero disables this trigger. +const finalizerGCThreshold = 32