diff options
author | 2022-09-16 00:53:03 -0700 | |
---|---|---|
committer | 2022-09-16 00:53:03 -0700 | |
commit | 0ce709d96abb48c747f5c93033c9a80fe79ee3bc (patch) | |
tree | f535a53c23fd95154b36ceab7c38c8e3a0275c89 /src/bun.js/api | |
parent | fd808dec524c60ba18c620e27b205828760a6e41 (diff) | |
download | bun-0ce709d96abb48c747f5c93033c9a80fe79ee3bc.tar.gz bun-0ce709d96abb48c747f5c93033c9a80fe79ee3bc.tar.zst bun-0ce709d96abb48c747f5c93033c9a80fe79ee3bc.zip |
Make new HTTP client more stable
Diffstat (limited to 'src/bun.js/api')
-rw-r--r-- | src/bun.js/api/bun.zig | 34 | ||||
-rw-r--r-- | src/bun.js/api/server.zig | 50 |
2 files changed, 60 insertions, 24 deletions
diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig index a37d5d62c..3fafdc177 100644 --- a/src/bun.js/api/bun.zig +++ b/src/bun.js/api/bun.zig @@ -1101,6 +1101,9 @@ pub const Class = NewClass( .nanoseconds = .{ .rfn = nanoseconds, }, + .DO_NOT_USE_OR_YOU_WILL_BE_FIRED_mimalloc_dump = .{ + .rfn = dump_mimalloc, + }, .gzipSync = .{ .rfn = JSC.wrapWithHasContainer(JSZlib, "gzipSync", false, false, true), }, @@ -1191,6 +1194,18 @@ pub const Class = NewClass( }, ); +fn dump_mimalloc( + _: void, + globalThis: JSC.C.JSContextRef, + _: JSC.C.JSObjectRef, + _: JSC.C.JSObjectRef, + _: []const JSC.C.JSValueRef, + _: JSC.C.ExceptionRef, +) JSC.C.JSValueRef { + globalThis.bunVM().arena.dumpThreadStats(); + return JSC.JSValue.jsUndefined().asObjectRef(); +} + pub const Crypto = struct { const Hashers = @import("../../sha.zig"); @@ -2101,6 +2116,8 @@ pub const Timer = struct { return VirtualMachine.vm.timer.last_id; } + const Pool = bun.ObjectPool(Timeout, null, true, 1000); + pub const Timeout = struct { id: i32 = 0, callback: JSValue, @@ -2134,11 +2151,13 @@ pub const Timer = struct { if (comptime JSC.is_bindgen) unreachable; + var vm = global.bunVM(); + if (!this.cancelled) { if (this.repeat) { this.io_task.?.deinit(); - var task = Timeout.TimeoutTask.createOnJSThread(VirtualMachine.vm.allocator, global, this) catch unreachable; - VirtualMachine.vm.timer.timeouts.put(VirtualMachine.vm.allocator, this.id, this) catch unreachable; + var task = Timeout.TimeoutTask.createOnJSThread(vm.allocator, global, this) catch unreachable; + vm.timer.timeouts.put(vm.allocator, this.id, this) catch unreachable; this.io_task = task; task.schedule(); } @@ -2148,12 +2167,12 @@ pub const Timer = struct { if (this.repeat) return; - VirtualMachine.vm.timer.active -|= 1; - VirtualMachine.vm.active_tasks -|= 1; + vm.timer.active -|= 1; + vm.active_tasks -|= 1; } else { // the active tasks count is already cleared for canceled timeout, // add one here to neutralize the `-|= 1` in event loop. - VirtualMachine.vm.active_tasks +|= 1; + vm.active_tasks +|= 1; } this.clear(global); @@ -2168,8 +2187,9 @@ pub const Timer = struct { _ = VirtualMachine.vm.timer.timeouts.swapRemove(this.id); if (this.io_task) |task| { task.deinit(); + this.io_task = null; } - VirtualMachine.vm.allocator.destroy(this); + Pool.releaseValue(this); } }; @@ -2181,7 +2201,7 @@ pub const Timer = struct { repeat: bool, ) !void { if (comptime is_bindgen) unreachable; - var timeout = try VirtualMachine.vm.allocator.create(Timeout); + var timeout = Pool.first(globalThis.bunVM().allocator); js.JSValueProtect(globalThis.ref(), callback.asObjectRef()); timeout.* = Timeout{ .id = id, .callback = callback, .interval = countdown.toInt32(), .repeat = repeat }; var task = try Timeout.TimeoutTask.createOnJSThread(VirtualMachine.vm.allocator, globalThis, timeout); diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index b79e6c7ab..55b829caa 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -1850,6 +1850,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type { has_js_deinited: bool = false, listen_callback: JSC.AnyTask = undefined, allocator: std.mem.Allocator, + keeping_js_alive: bool = false, pub const Class = JSC.NewClass( ThisServer, @@ -1917,15 +1918,17 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type { } pub fn deinitIfWeCan(this: *ThisServer) void { - if (this.pending_requests == 0 and this.listener == null and this.has_js_deinited) + if (this.pending_requests == 0 and this.listener == null and this.has_js_deinited) { + this.deref(); this.deinit(); + } } pub fn stop(this: *ThisServer) void { if (this.listener) |listener| { - listener.close(); this.listener = null; - this.vm.disable_run_us_loop = false; + this.deref(); + listener.close(); } this.deinitIfWeCan(); @@ -2038,22 +2041,26 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type { this.listener = socket; const needs_post_handler = this.vm.uws_event_loop == null; this.vm.uws_event_loop = uws.Loop.get(); - this.listen_callback = JSC.AnyTask.New(ThisServer, run).init(this); - this.vm.eventLoop().enqueueTask(JSC.Task.init(&this.listen_callback)); + this.ref(); + if (needs_post_handler) { _ = this.vm.uws_event_loop.?.addPostHandler(*JSC.EventLoop, this.vm.eventLoop(), JSC.EventLoop.tick); + _ = this.vm.uws_event_loop.?.addPreHandler(*JSC.EventLoop, this.vm.eventLoop(), JSC.EventLoop.tick); } } - pub fn run(this: *ThisServer) void { - // this.app.addServerName(hostname_pattern: [*:0]const u8) + pub fn ref(this: *ThisServer) void { + if (this.keeping_js_alive) return; + + this.vm.us_loop_reference_count +|= 1; + this.keeping_js_alive = true; + } - // we do not increment the reference count here - // uWS manages running the loop, so it is unnecessary - // this.vm.us_loop_reference_count +|= 1; - this.vm.disable_run_us_loop = true; + pub fn deref(this: *ThisServer) void { + if (!this.keeping_js_alive) return; - this.app.run(); + this.vm.us_loop_reference_count -|= 1; + this.keeping_js_alive = false; } pub fn onBunInfoRequest(this: *ThisServer, req: *uws.Request, resp: *App.Response) void { @@ -2286,11 +2293,20 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type { this.app.get("/src:/*", *ThisServer, this, onSrcRequest); } - this.app.listenWithConfig(*ThisServer, this, onListen, .{ - .port = this.config.port, - .host = this.config.hostname, - .options = 0, - }); + const hostname = bun.span(this.config.hostname); + + if (!(hostname.len == 0 or strings.eqlComptime(hostname, "0.0.0.0"))) { + this.app.listenWithConfig(*ThisServer, this, onListen, .{ + .port = this.config.port, + .options = 0, + }); + } else { + this.app.listenWithConfig(*ThisServer, this, onListen, .{ + .port = this.config.port, + .host = this.config.hostname, + .options = 0, + }); + } } }; } |