From 1ce2a10f2dffc5976dcc0e5bc91029f18ee11daf Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Tue, 24 Dec 2024 00:55:43 -0800 Subject: [PATCH 1/3] experiment: tweak GC timings --- bench/snippets/read-file-large.mjs | 17 +++++++++++++++++ src/bun.js/bindings/ZigGlobalObject.cpp | 21 +++++++++++++++++++-- src/bun.js/bindings/bindings.cpp | 2 +- src/bun.js/event_loop.zig | 18 ++++++++++-------- 4 files changed, 47 insertions(+), 11 deletions(-) create mode 100644 bench/snippets/read-file-large.mjs diff --git a/bench/snippets/read-file-large.mjs b/bench/snippets/read-file-large.mjs new file mode 100644 index 00000000000000..ab34fe0841db2e --- /dev/null +++ b/bench/snippets/read-file-large.mjs @@ -0,0 +1,17 @@ +import { readFile } from "node:fs/promises"; + +import { writeFileSync } from "node:fs"; + +(function () { + writeFileSync("/tmp/bun-bench-large.text", Buffer.alloc(1024 * 1024 * 8, "abcdefg!")); +})(); +if (globalThis.Bun) { + Bun.gc(true); +} + +console.log("Before:", "RSS", (process.memoryUsage.rss() / 1024 / 1024) | 0, "MB"); + +for (let i = 0; i < 1024; i++) { + await readFile("/tmp/bun-bench-large.text"); +} +console.log("After:", "RSS", (process.memoryUsage.rss() / 1024 / 1024) | 0, "MB"); diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index a8a8ea91cebb12..e8bbb2698f1971 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -218,6 +218,18 @@ extern "C" unsigned getJSCBytecodeCacheVersion() return getWebKitBytecodeCacheVersion(); } +extern "C" void Bun__onEachMicrotaskTick(void* bun_vm, JSC::VM* vm); + +static void defaultOnEachMicrotaskTick(JSC::VM& vm) +{ + Bun__onEachMicrotaskTick(clientData(vm)->bunVM, &vm); +} + +static void defaultOnEachMicrotaskTickWithVM(void* bun_vm, JSC::VM& vm) +{ + Bun__onEachMicrotaskTick(bun_vm, &vm); +} + extern "C" void JSCInitialize(const char* envp[], size_t envc, void (*onCrash)(const char* ptr, size_t length), bool evalMode) { static bool has_loaded_jsc = false; @@ -799,6 +811,8 @@ static void checkIfNextTickWasCalledDuringMicrotask(JSC::VM& vm) globalObject->resetOnEachMicrotaskTick(); queue->drain(vm, globalObject); } + + Bun__onEachMicrotaskTick(globalObject->m_bunVM, &vm); } static void cleanupAsyncHooksData(JSC::VM& vm) @@ -810,7 +824,8 @@ static void cleanupAsyncHooksData(JSC::VM& vm) vm.setOnEachMicrotaskTick(&checkIfNextTickWasCalledDuringMicrotask); checkIfNextTickWasCalledDuringMicrotask(vm); } else { - vm.setOnEachMicrotaskTick(nullptr); + vm.setOnEachMicrotaskTick(&defaultOnEachMicrotaskTick); + Bun__onEachMicrotaskTick(globalObject->m_bunVM, &vm); } } @@ -856,7 +871,7 @@ void Zig::GlobalObject::resetOnEachMicrotaskTick() vm.setOnEachMicrotaskTick(&cleanupAsyncHooksData); } else { if (this->m_nextTickQueue) { - vm.setOnEachMicrotaskTick(nullptr); + vm.setOnEachMicrotaskTick(&defaultOnEachMicrotaskTick); } else { vm.setOnEachMicrotaskTick(&checkIfNextTickWasCalledDuringMicrotask); } @@ -923,8 +938,10 @@ extern "C" JSC__JSGlobalObject* Zig__GlobalObject__create(void* console_client, globalObject->resetOnEachMicrotaskTick(); Bun::JSNextTickQueue* queue = jsCast(nextTickQueue); queue->drain(vm, globalObject); + Bun__onEachMicrotaskTick(globalObject->m_bunVM, &vm); return; } + Bun__onEachMicrotaskTick(globalObject->m_bunVM, &vm); }); if (executionContextId > -1) { diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index cb1a0446df1359..b4daefa5ef6e61 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -5709,7 +5709,7 @@ extern "C" JSC__JSValue JSC__JSValue__createRopeString(JSC__JSValue JSValue0, JS extern "C" size_t JSC__VM__blockBytesAllocated(JSC__VM* vm) { #if ENABLE(RESOURCE_USAGE) - return vm->heap.blockBytesAllocated() + vm->heap.extraMemorySize(); + return vm->heap.blockBytesAllocated() + vm->heap.extraMemorySize() + vm->heap.externalMemorySize(); #else return 0; #endif diff --git a/src/bun.js/event_loop.zig b/src/bun.js/event_loop.zig index 03e24fe55bc5ac..fafef6a8fa90ad 100644 --- a/src/bun.js/event_loop.zig +++ b/src/bun.js/event_loop.zig @@ -543,6 +543,9 @@ pub const GarbageCollectionController = struct { gc_repeating_timer_fast: bool = true, disabled: bool = false, + pub export fn Bun__onEachMicrotaskTick(vm: *VirtualMachine, jsc_vm: *JSC.VM) void { + vm.gc_controller.processGCTimerWithHeapSize(jsc_vm, jsc_vm.blockBytesAllocated()); + } pub fn init(this: *GarbageCollectionController, vm: *VirtualMachine) void { const actual = uws.Loop.get(); this.gc_timer = uws.Timer.createFallthrough(actual, this); @@ -612,7 +615,7 @@ pub const GarbageCollectionController = struct { pub fn onGCRepeatingTimer(timer: *uws.Timer) callconv(.C) void { var this = timer.as(*GarbageCollectionController); const prev_heap_size = this.gc_last_heap_size_on_repeating_timer; - this.performGC(); + this.performGC(this.bunVM().jsc); this.gc_last_heap_size_on_repeating_timer = this.gc_last_heap_size; if (prev_heap_size == this.gc_last_heap_size_on_repeating_timer) { this.heap_size_didnt_change_for_repeating_timer_ticks_count +|= 1; @@ -652,7 +655,7 @@ pub const GarbageCollectionController = struct { this.updateGCRepeatTimer(.fast); if (this_heap_size > prev * 2) { - this.performGC(); + this.performGC(vm); } else { this.scheduleGCTimer(); } @@ -661,17 +664,16 @@ pub const GarbageCollectionController = struct { .scheduled => { if (this_heap_size > prev * 2) { this.updateGCRepeatTimer(.fast); - this.performGC(); + this.performGC(vm); } }, } } - pub fn performGC(this: *GarbageCollectionController) void { + pub fn performGC(this: *GarbageCollectionController, js_vm: *JSC.VM) void { if (this.disabled) return; - var vm = this.bunVM().jsc; - vm.collectAsync(); - this.gc_last_heap_size = vm.blockBytesAllocated(); + js_vm.collectAsync(); + this.gc_last_heap_size = js_vm.blockBytesAllocated(); } pub const GCTimerState = enum { @@ -1618,7 +1620,7 @@ pub const EventLoop = struct { /// Asynchronously run the garbage collector and track how much memory is now allocated pub fn performGC(this: *EventLoop) void { - this.virtual_machine.gc_controller.performGC(); + this.virtual_machine.gc_controller.performGC(this.virtual_machine.jsc); } pub fn wakeup(this: *EventLoop) void { From 4eefe8eb2999b4c019526661e7561fe9ebd7575a Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Tue, 24 Dec 2024 03:48:14 -0800 Subject: [PATCH 2/3] Bump mimalloc --- cmake/targets/BuildMimalloc.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/targets/BuildMimalloc.cmake b/cmake/targets/BuildMimalloc.cmake index 1e88a1a5f0e7f9..08921be5138889 100644 --- a/cmake/targets/BuildMimalloc.cmake +++ b/cmake/targets/BuildMimalloc.cmake @@ -4,7 +4,7 @@ register_repository( REPOSITORY oven-sh/mimalloc COMMIT - 82b2c2277a4d570187c07b376557dc5bde81d848 + f605cb73e524cbfcab36c86cc351a6310640a3fb ) set(MIMALLOC_CMAKE_ARGS From f5e874e1b5a33177e909d920ddff3b3949ecdb10 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Tue, 24 Dec 2024 03:58:29 -0800 Subject: [PATCH 3/3] Update BuildMimalloc.cmake --- cmake/targets/BuildMimalloc.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/targets/BuildMimalloc.cmake b/cmake/targets/BuildMimalloc.cmake index 08921be5138889..0023f367a611c5 100644 --- a/cmake/targets/BuildMimalloc.cmake +++ b/cmake/targets/BuildMimalloc.cmake @@ -4,7 +4,7 @@ register_repository( REPOSITORY oven-sh/mimalloc COMMIT - f605cb73e524cbfcab36c86cc351a6310640a3fb + 7085b6cec31641fddaca3d40932cda82e91baf07 ) set(MIMALLOC_CMAKE_ARGS