From c8742e71a9239e57bad3c66fcd409ab6f2425648 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Wed, 4 Sep 2024 16:31:03 -0700 Subject: [PATCH] Experiment: run incremental sweeper sometimes --- src/bun.js/bindings/bindings.cpp | 10 +++++++++- src/bun.js/event_loop.zig | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index a9f3cc2ddc..c8257d1f34 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -20,7 +20,7 @@ #include "BunClientData.h" #include "GCDefferalContext.h" - +#include "JavaScriptCore/IncrementalSweeper.h" #include "JavaScriptCore/AggregateError.h" #include "JavaScriptCore/BytecodeIndex.h" #include "JavaScriptCore/CodeBlock.h" @@ -66,6 +66,7 @@ #include "wtf/Assertions.h" #include "wtf/Compiler.h" +#include "wtf/MonotonicTime.h" #include "wtf/text/ExternalStringImpl.h" #include "wtf/text/OrdinalNumber.h" #include "wtf/text/StringCommon.h" @@ -3035,6 +3036,13 @@ void JSC__AnyPromise__wrap(JSC__JSGlobalObject* globalObject, EncodedJSValue enc ASSERT_NOT_REACHED_WITH_MESSAGE("Non-promise value passed to AnyPromise.wrap"); } +extern "C" void JSC__VM__incrementalSweep(JSC::VM* vmPtr, uint64_t milliseconds) +{ + auto& vm = *vmPtr; + double deadlineSeconds = milliseconds / 1000.0; + vm.heap.sweeper().doWorkUntil(vm, MonotonicTime::fromRawSeconds(deadlineSeconds)); +} + JSC__JSValue JSC__JSPromise__wrap(JSC__JSGlobalObject* globalObject, void* ctx, JSC__JSValue (*func)(void*, JSC__JSGlobalObject*)) { auto& vm = globalObject->vm(); diff --git a/src/bun.js/event_loop.zig b/src/bun.js/event_loop.zig index c441bed170..da089c2c29 100644 --- a/src/bun.js/event_loop.zig +++ b/src/bun.js/event_loop.zig @@ -541,6 +541,8 @@ pub const GarbageCollectionController = struct { gc_repeating_timer_fast: bool = true, disabled: bool = false, + const log = bun.Output.scoped(.GC, false); + pub fn init(this: *GarbageCollectionController, vm: *VirtualMachine) void { const actual = uws.Loop.get(); this.gc_timer = uws.Timer.createFallthrough(actual, this); @@ -568,7 +570,10 @@ pub const GarbageCollectionController = struct { this.gc_repeating_timer.set(this, onGCRepeatingTimer, gc_timer_interval, gc_timer_interval); } + extern fn JSC__VM__incrementalSweep(vm: *JSC.VM, deadlineSeconds: u64) void; + pub fn scheduleGCTimer(this: *GarbageCollectionController) void { + log("schedule", .{}); this.gc_timer_state = .scheduled; this.gc_timer.set(this, onGCTimer, 16, 0); } @@ -580,7 +585,9 @@ pub const GarbageCollectionController = struct { pub fn onGCTimer(timer: *uws.Timer) callconv(.C) void { var this = timer.as(*GarbageCollectionController); if (this.disabled) return; + log("onGCTimer", .{}); this.gc_timer_state = .run_on_next_tick; + this.runIncrementalSweep(this.bunVM().jsc, 1); } // We want to always run GC once in awhile @@ -603,6 +610,8 @@ pub const GarbageCollectionController = struct { this.gc_repeating_timer_fast = false; this.gc_repeating_timer.set(this, onGCRepeatingTimer, 30_000, 30_000); this.heap_size_didnt_change_for_repeating_timer_ticks_count = 0; + } else if (setting == .slow and !this.gc_repeating_timer_fast) { + this.runIncrementalSweep(this.bunVM().jsc, 1); } } @@ -626,9 +635,15 @@ pub const GarbageCollectionController = struct { pub fn processGCTimer(this: *GarbageCollectionController) void { if (this.disabled) return; var vm = this.bunVM().jsc; + log("processGCTimer", .{}); this.processGCTimerWithHeapSize(vm, vm.blockBytesAllocated()); } + pub fn runIncrementalSweep(_: *GarbageCollectionController, vm: *JSC.VM, deadlineMs: u64) void { + log("runIncrementalSweep({d})", .{deadlineMs}); + JSC__VM__incrementalSweep(vm, deadlineMs); + } + fn processGCTimerWithHeapSize(this: *GarbageCollectionController, vm: *JSC.VM, this_heap_size: usize) void { const prev = this.gc_last_heap_size; @@ -649,6 +664,7 @@ pub const GarbageCollectionController = struct { this.updateGCRepeatTimer(.fast); if (this_heap_size > prev * 2) { + this.runIncrementalSweep(vm, 1); this.performGC(); } else { this.scheduleGCTimer(); @@ -657,6 +673,7 @@ pub const GarbageCollectionController = struct { }, .scheduled => { if (this_heap_size > prev * 2) { + this.runIncrementalSweep(vm, 1); this.updateGCRepeatTimer(.fast); this.performGC(); }