aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-05-21 21:29:17 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-05-21 21:29:17 -0700
commit9f935c4683e30f40e7c85087d42ab44e65b3c907 (patch)
treeacf2fe92da381a14627a89299933240886b60316
parent3c57911b593856feac0799bbb28917bb45ed118f (diff)
downloadbun-9f935c4683e30f40e7c85087d42ab44e65b3c907.tar.gz
bun-9f935c4683e30f40e7c85087d42ab44e65b3c907.tar.zst
bun-9f935c4683e30f40e7c85087d42ab44e65b3c907.zip
[internal] Use `HiveArray` instead of bespoke memory allocator in Bun.serve()
No performance or memory usage change Just removing some duplicate code
-rw-r--r--src/bun.js/api/server.zig99
-rw-r--r--src/hive_array.zig4
2 files changed, 14 insertions, 89 deletions
diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig
index d3a202364..7a4fd4552 100644
--- a/src/bun.js/api/server.zig
+++ b/src/bun.js/api/server.zig
@@ -978,80 +978,6 @@ const HTTPStatusText = struct {
}
};
-pub fn NewRequestContextStackAllocator(comptime RequestContext: type, comptime count: usize) type {
- // Pre-allocate up to 2048 requests
- // use a bitset to track which ones are used
- return struct {
- buf: [count]RequestContext = undefined,
- unused: Set = undefined,
- fallback_allocator: std.mem.Allocator = undefined,
-
- pub const Set = std.bit_set.ArrayBitSet(usize, count);
-
- pub fn get(this: *@This()) std.mem.Allocator {
- this.unused = Set.initFull();
- return .{
- .ptr = this,
- .vtable = &.{
- .alloc = alloc,
- .resize = resize,
- .free = free,
- },
- };
- }
-
- fn alloc(self_: *anyopaque, a: usize, b: u8, d: usize) ?[*]u8 {
- const self = @ptrCast(*@This(), @alignCast(@alignOf(@This()), self_));
- if (self.unused.findFirstSet()) |i| {
- self.unused.unset(i);
- return std.mem.asBytes(&self.buf[i]);
- }
-
- return self.fallback_allocator.rawAlloc(a, b, d);
- }
-
- fn resize(
- _: *anyopaque,
- _: []u8,
- _: u8,
- _: usize,
- _: usize,
- ) bool {
- unreachable;
- }
-
- fn sliceContainsSlice(container: []u8, slice: []u8) bool {
- return @ptrToInt(slice.ptr) >= @ptrToInt(container.ptr) and
- (@ptrToInt(slice.ptr) + slice.len) <= (@ptrToInt(container.ptr) + container.len);
- }
-
- fn free(
- self_: *anyopaque,
- buf: []u8,
- buf_align: u8,
- return_address: usize,
- ) void {
- const self = @ptrCast(*@This(), @alignCast(@alignOf(@This()), self_));
- const bytes = std.mem.asBytes(&self.buf);
- if (sliceContainsSlice(bytes, buf)) {
- const index = if (bytes[0..buf.len].ptr != buf.ptr)
- (@ptrToInt(buf.ptr) - @ptrToInt(bytes)) / @sizeOf(RequestContext)
- else
- @as(usize, 0);
-
- if (comptime Environment.allow_assert) {
- std.debug.assert(@intToPtr(*RequestContext, @ptrToInt(buf.ptr)) == &self.buf[index]);
- std.debug.assert(!self.unused.isSet(index));
- }
-
- self.unused.set(index);
- } else {
- self.fallback_allocator.rawFree(buf, buf_align, return_address);
- }
- }
- };
-}
-
// This is defined separately partially to work-around an LLVM debugger bug.
fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comptime ThisServer: type) type {
return struct {
@@ -1059,9 +985,12 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
const ctxLog = Output.scoped(.RequestContext, false);
const App = uws.NewApp(ssl_enabled);
pub threadlocal var pool: ?*RequestContext.RequestContextStackAllocator = null;
- pub threadlocal var pool_allocator: std.mem.Allocator = undefined;
pub const ResponseStream = JSC.WebCore.HTTPServerWritable(ssl_enabled);
- pub const RequestContextStackAllocator = NewRequestContextStackAllocator(RequestContext, 2048);
+
+ // This pre-allocates up to 2,048 RequestContext structs.
+ // It costs about 655,632 bytes.
+ pub const RequestContextStackAllocator = bun.HiveArray(RequestContext, 2048).Fallback;
+
pub const name = "HTTPRequestContext" ++ (if (debug_mode) "Debug" else "") ++ (if (ThisServer.ssl_enabled) "TLS" else "");
pub const shim = JSC.Shimmer("Bun", name, @This());
@@ -1635,7 +1564,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
this.request_body = null;
}
- server.request_pool_allocator.destroy(this);
+ server.request_pool_allocator.put(this);
}
fn writeHeaders(
@@ -4385,7 +4314,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
base_url_string_for_joining: string = "",
config: ServerConfig = ServerConfig{},
pending_requests: usize = 0,
- request_pool_allocator: std.mem.Allocator = undefined,
+ request_pool_allocator: *RequestContext.RequestContextStackAllocator = undefined,
listen_callback: JSC.AnyTask = undefined,
allocator: std.mem.Allocator,
@@ -4956,15 +4885,11 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
if (RequestContext.pool == null) {
RequestContext.pool = server.allocator.create(RequestContext.RequestContextStackAllocator) catch @panic("Out of memory!");
- RequestContext.pool.?.* = .{
- .fallback_allocator = server.allocator,
- };
- server.request_pool_allocator = RequestContext.pool.?.get();
- RequestContext.pool_allocator = server.request_pool_allocator;
- } else {
- server.request_pool_allocator = RequestContext.pool_allocator;
+ RequestContext.pool.?.* = RequestContext.RequestContextStackAllocator.init(server.allocator);
}
+ server.request_pool_allocator = RequestContext.pool.?;
+
return server;
}
@@ -5133,7 +5058,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
JSC.markBinding(@src());
this.pending_requests += 1;
req.setYield(false);
- var ctx = this.request_pool_allocator.create(RequestContext) catch @panic("ran out of memory");
+ var ctx = this.request_pool_allocator.tryGet() catch @panic("ran out of memory");
ctx.create(this, req, resp);
var request_object = this.allocator.create(JSC.WebCore.Request) catch unreachable;
var body = JSC.WebCore.InitRequestBodyValue(.{ .Null = {} }) catch unreachable;
@@ -5236,7 +5161,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
JSC.markBinding(@src());
this.pending_requests += 1;
req.setYield(false);
- var ctx = this.request_pool_allocator.create(RequestContext) catch @panic("ran out of memory");
+ var ctx = this.request_pool_allocator.tryGet() catch @panic("ran out of memory");
ctx.create(this, req, resp);
var request_object = this.allocator.create(JSC.WebCore.Request) catch unreachable;
var body = JSC.WebCore.InitRequestBodyValue(.{ .Null = {} }) catch unreachable;
diff --git a/src/hive_array.zig b/src/hive_array.zig
index cc032c44f..a29fe6842 100644
--- a/src/hive_array.zig
+++ b/src/hive_array.zig
@@ -34,7 +34,7 @@ pub fn HiveArray(comptime T: type, comptime capacity: u16) type {
self.available.unset(index);
}
- pub fn indexOf(self: *const Self, value: *const T) ?u63 {
+ pub fn indexOf(self: *const Self, value: *const T) ?u32 {
const start = &self.buffer;
const end = @ptrCast([*]const T, start) + capacity;
if (!(@ptrToInt(value) >= @ptrToInt(start) and @ptrToInt(value) < @ptrToInt(end)))
@@ -44,7 +44,7 @@ pub fn HiveArray(comptime T: type, comptime capacity: u16) type {
const index = (@ptrToInt(value) - @ptrToInt(start)) / @sizeOf(T);
assert(index < capacity);
assert(&self.buffer[index] == value);
- return @truncate(u63, index);
+ return @intCast(u32, index);
}
pub fn in(self: *const Self, value: *const T) bool {