aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-07-29 04:24:08 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-07-29 04:24:08 -0700
commitc708cd8f2616b75eb1bfb9319a2d43a7c194d1bc (patch)
tree9df00826b972ae4e31d6bff49ac28890e562d4f0
parentbcb6dc78060f4309c08b63827b10e3d55632d647 (diff)
downloadbun-c708cd8f2616b75eb1bfb9319a2d43a7c194d1bc.tar.gz
bun-c708cd8f2616b75eb1bfb9319a2d43a7c194d1bc.tar.zst
bun-c708cd8f2616b75eb1bfb9319a2d43a7c194d1bc.zip
experiment: use bmalloc/libpas instead of mimalloc in most places
-rw-r--r--src/bmalloc_allocator.zig66
-rw-r--r--src/boringssl.zig8
-rw-r--r--src/bun.js/api/bun/subprocess.zig4
-rw-r--r--src/bun.js/api/filesystem_router.zig2
-rw-r--r--src/bun.js/api/server.zig2
-rw-r--r--src/bun.js/base.zig50
-rw-r--r--src/bun.js/bindings/bindings.zig15
-rw-r--r--src/bun.js/bindings/exports.zig15
-rw-r--r--src/bun.js/bindings/wtf-bindings.cpp42
-rw-r--r--src/bun.zig19
-rw-r--r--src/bun_js.zig4
-rw-r--r--src/cli.zig3
-rw-r--r--src/http_client_async.zig17
13 files changed, 165 insertions, 82 deletions
diff --git a/src/bmalloc_allocator.zig b/src/bmalloc_allocator.zig
new file mode 100644
index 000000000..813246d9f
--- /dev/null
+++ b/src/bmalloc_allocator.zig
@@ -0,0 +1,66 @@
+const mem = @import("std").mem;
+const builtin = @import("std").builtin;
+const std = @import("std");
+
+pub const bmalloc = struct {
+ pub fn memalign(alignment: usize, size: usize) ?*anyopaque {
+ return bun__bmalloc__memalign(alignment, size);
+ }
+ pub fn free(ptr: *anyopaque) void {
+ return bun__bmalloc__free(ptr);
+ }
+ pub fn realloc(ptr: *anyopaque, size: usize) ?*anyopaque {
+ return bun__bmalloc__realloc(ptr, size);
+ }
+ pub fn allocatedSize(ptr: *anyopaque) usize {
+ return bun__bmalloc__size(ptr);
+ }
+
+ extern fn bun__bmalloc__memalign(alignment: usize, size: usize) ?*anyopaque;
+ extern fn bun__bmalloc__free(*anyopaque) void;
+ extern fn bun__bmalloc__realloc(*anyopaque, usize) ?*anyopaque;
+ extern fn bun__bmalloc__size(*anyopaque) usize;
+
+ pub extern fn bmalloc_try_allocate_zeroed(size: usize) ?*anyopaque;
+ pub extern fn bmalloc_deallocate(*anyopaque) void;
+ pub extern fn bmalloc_get_allocation_size(?*const anyopaque) usize;
+};
+pub const free = bmalloc.free;
+
+const Allocator = mem.Allocator;
+const assert = std.debug.assert;
+const CAllocator = struct {
+ pub const supports_posix_memalign = true;
+
+ fn alloc(_: *anyopaque, len: usize, log2_align: u8, _: usize) ?[*]u8 {
+ const alignment = @as(usize, 1) << @as(Allocator.Log2Align, @intCast(log2_align));
+ // The posix_memalign only accepts alignment values that are a
+ // multiple of the pointer size
+ const eff_alignment = @max(alignment, @sizeOf(usize));
+ return @ptrCast(bmalloc.memalign(eff_alignment, len));
+ }
+
+ fn resize(_: *anyopaque, buf: []u8, _: u8, new_len: usize, _: usize) bool {
+ return bmalloc.realloc(buf.ptr, new_len) != null;
+ }
+
+ fn free(
+ _: *anyopaque,
+ buf: []u8,
+ _: u8,
+ _: usize,
+ ) void {
+ bmalloc.free(buf.ptr);
+ }
+
+ pub const VTable = Allocator.VTable{
+ .alloc = &alloc,
+ .resize = &resize,
+ .free = &CAllocator.free,
+ };
+};
+
+pub const c_allocator = Allocator{
+ .ptr = undefined,
+ .vtable = &CAllocator.VTable,
+};
diff --git a/src/boringssl.zig b/src/boringssl.zig
index a12c356d9..c53c0e7d7 100644
--- a/src/boringssl.zig
+++ b/src/boringssl.zig
@@ -60,18 +60,16 @@ pub fn initClient() *boring.SSL {
// may result in deadlocks, crashes, or memory corruption.
export fn OPENSSL_memory_alloc(size: usize) ?*anyopaque {
- return bun.Mimalloc.mi_malloc(size);
+ return bun.bmalloc.bmalloc_try_allocate_zeroed(size);
}
// BoringSSL always expects memory to be zero'd
export fn OPENSSL_memory_free(ptr: *anyopaque) void {
- const len = bun.Mimalloc.mi_usable_size(ptr);
- @memset(@as([*]u8, @ptrCast(ptr))[0..len], 0);
- bun.Mimalloc.mi_free(ptr);
+ bun.bmalloc.bmalloc_deallocate(ptr);
}
export fn OPENSSL_memory_get_size(ptr: ?*const anyopaque) usize {
- return bun.Mimalloc.mi_usable_size(ptr);
+ return bun.bmalloc.bmalloc_get_allocation_size(ptr);
}
test "load" {
diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig
index 4fb02b8af..f1fbd242a 100644
--- a/src/bun.js/api/bun/subprocess.zig
+++ b/src/bun.js/api/bun/subprocess.zig
@@ -1372,8 +1372,8 @@ pub const Subprocess = struct {
return .zero;
},
// stdout and stderr only uses allocator and default_max_buffer_size if they are pipes and not a array buffer
- .stdout = Readable.init(stdio[std.os.STDOUT_FILENO], stdout_pipe[0], jsc_vm.allocator, default_max_buffer_size),
- .stderr = Readable.init(stdio[std.os.STDERR_FILENO], stderr_pipe[0], jsc_vm.allocator, default_max_buffer_size),
+ .stdout = Readable.init(stdio[std.os.STDOUT_FILENO], stdout_pipe[0], bun.default_allocator, default_max_buffer_size),
+ .stderr = Readable.init(stdio[std.os.STDERR_FILENO], stderr_pipe[0], bun.default_allocator, default_max_buffer_size),
.on_exit_callback = if (on_exit_callback != .zero) JSC.Strong.create(on_exit_callback, globalThis) else .{},
.is_sync = is_sync,
};
diff --git a/src/bun.js/api/filesystem_router.zig b/src/bun.js/api/filesystem_router.zig
index 216f66b7f..814f9c9b6 100644
--- a/src/bun.js/api/filesystem_router.zig
+++ b/src/bun.js/api/filesystem_router.zig
@@ -550,7 +550,7 @@ pub const MatchedRoute = struct {
}
if (this.needs_deinit) {
if (this.route.pathname.len > 0 and bun.Mimalloc.mi_is_in_heap_region(this.route.pathname.ptr)) {
- bun.Mimalloc.mi_free(bun.constStrToU8(this.route.pathname).ptr);
+ bun.default_allocator.free(bun.constStrToU8(this.route.pathname));
}
this.params_list_holder.deinit(bun.default_allocator);
diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig
index 801745aee..28bcb45a4 100644
--- a/src/bun.js/api/server.zig
+++ b/src/bun.js/api/server.zig
@@ -5104,7 +5104,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
.config = config,
.base_url_string_for_joining = bun.default_allocator.dupe(u8, strings.trim(config.base_url.href, "/")) catch unreachable,
.vm = JSC.VirtualMachine.get(),
- .allocator = Arena.getThreadlocalDefault(),
+ .allocator = bun.default_allocator,
};
if (RequestContext.pool == null) {
diff --git a/src/bun.js/base.zig b/src/bun.js/base.zig
index 579a0975a..0528eb8d1 100644
--- a/src/bun.js/base.zig
+++ b/src/bun.js/base.zig
@@ -1824,31 +1824,31 @@ pub const ArrayBuffer = extern struct {
return this.value;
}
- // If it's not a mimalloc heap buffer, we're not going to call a deallocator
- if (this.len > 0 and !bun.Mimalloc.mi_is_in_heap_region(this.ptr)) {
- log("toJS but will never free: {d} bytes", .{this.len});
-
- if (this.typed_array_type == .ArrayBuffer) {
- return JSC.JSValue.fromRef(JSC.C.JSObjectMakeArrayBufferWithBytesNoCopy(
- ctx,
- this.ptr,
- this.byte_len,
- null,
- null,
- exception,
- ));
- }
-
- return JSC.JSValue.fromRef(JSC.C.JSObjectMakeTypedArrayWithBytesNoCopy(
- ctx,
- this.typed_array_type.toC(),
- this.ptr,
- this.byte_len,
- null,
- null,
- exception,
- ));
- }
+ // // If it's not a mimalloc heap buffer, we're not going to call a deallocator
+ // if (this.len > 0 and !bun.Mimalloc.mi_is_in_heap_region(this.ptr)) {
+ // log("toJS but will never free: {d} bytes", .{this.len});
+
+ // if (this.typed_array_type == .ArrayBuffer) {
+ // return JSC.JSValue.fromRef(JSC.C.JSObjectMakeArrayBufferWithBytesNoCopy(
+ // ctx,
+ // this.ptr,
+ // this.byte_len,
+ // null,
+ // null,
+ // exception,
+ // ));
+ // }
+
+ // return JSC.JSValue.fromRef(JSC.C.JSObjectMakeTypedArrayWithBytesNoCopy(
+ // ctx,
+ // this.typed_array_type.toC(),
+ // this.ptr,
+ // this.byte_len,
+ // null,
+ // null,
+ // exception,
+ // ));
+ // }
return this.toJSUnchecked(ctx, exception);
}
diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig
index 4f533b9d9..8be5d878f 100644
--- a/src/bun.js/bindings/bindings.zig
+++ b/src/bun.js/bindings/bindings.zig
@@ -727,6 +727,10 @@ pub const ZigString = extern struct {
return untagged(this._unsafe_ptr_do_not_use)[0..@min(this.len, std.math.maxInt(u32))];
}
+ pub fn untaggedPtr(this: *const ZigString) [*]const u8 {
+ return untagged(this._unsafe_ptr_do_not_use);
+ }
+
pub fn dupe(this: ZigString, allocator: std.mem.Allocator) ![]const u8 {
return try allocator.dupe(u8, this.slice());
}
@@ -837,11 +841,12 @@ pub const ZigString = extern struct {
}
inline fn assertGlobal(this: *const ZigString) void {
- if (comptime bun.Environment.allow_assert) {
- std.debug.assert(this.len == 0 or
- bun.Mimalloc.mi_is_in_heap_region(untagged(this._unsafe_ptr_do_not_use)) or
- bun.Mimalloc.mi_check_owned(untagged(this._unsafe_ptr_do_not_use)));
- }
+ _ = this;
+ // if (comptime bun.Environment.allow_assert) {
+ // std.debug.assert(this.len == 0 or
+ // bun.Mimalloc.mi_is_in_heap_region(untagged(this._unsafe_ptr_do_not_use)) or
+ // bun.Mimalloc.mi_check_owned(untagged(this._unsafe_ptr_do_not_use)));
+ // }
}
pub fn toValue(this: *const ZigString, global: *JSGlobalObject) JSValue {
diff --git a/src/bun.js/bindings/exports.zig b/src/bun.js/bindings/exports.zig
index 20c110d52..ca70aa5ba 100644
--- a/src/bun.js/bindings/exports.zig
+++ b/src/bun.js/bindings/exports.zig
@@ -243,22 +243,17 @@ const Mimalloc = @import("../../allocators/mimalloc.zig");
export fn ZigString__free(raw: [*]const u8, len: usize, allocator_: ?*anyopaque) void {
var allocator: std.mem.Allocator = @as(*std.mem.Allocator, @ptrCast(@alignCast(allocator_ orelse return))).*;
- var ptr = ZigString.init(raw[0..len]).slice().ptr;
- if (comptime Environment.allow_assert) {
- std.debug.assert(Mimalloc.mi_is_in_heap_region(ptr));
- }
+ var ptr = ZigString.init(raw[0..len]).untaggedPtr();
+ // if (comptime Environment.allow_assert) {
+ // std.debug.assert(Mimalloc.mi_is_in_heap_region(ptr));
+ // }
var str = ptr[0..len];
allocator.free(str);
}
export fn ZigString__free_global(ptr: [*]const u8, len: usize) void {
- var untagged = @as(*anyopaque, @ptrFromInt(@intFromPtr(ZigString.init(ptr[0..len]).slice().ptr)));
- if (comptime Environment.allow_assert) {
- std.debug.assert(Mimalloc.mi_is_in_heap_region(ptr));
- }
- // we must untag the string pointer
- Mimalloc.mi_free(untagged);
+ bun.free(@constCast(ZigString.init(ptr[0..len]).untaggedPtr()));
}
export fn Zig__getAPIGlobals(count: *usize) [*]JSC.C.JSClassRef {
diff --git a/src/bun.js/bindings/wtf-bindings.cpp b/src/bun.js/bindings/wtf-bindings.cpp
index 5c0e593d7..5bc37467a 100644
--- a/src/bun.js/bindings/wtf-bindings.cpp
+++ b/src/bun.js/bindings/wtf-bindings.cpp
@@ -2,7 +2,47 @@
#include "wtf/text/Base64.h"
#include "wtf/StackTrace.h"
-#include "wtf/dtoa.h"
+#include "bmalloc/bmalloc.h"
+
+extern "C" void bun__bmalloc__init()
+{
+ WTF::initializeMainThread();
+}
+
+extern "C" void* bun__bmalloc__memalign(size_t alignment, size_t size)
+{
+ return bmalloc::api::tryMemalign(alignment, size);
+}
+
+extern "C" void bun__bmalloc__free(void* ptr)
+{
+ bmalloc::api::free(ptr);
+}
+
+extern "C" void* bun__bmalloc__realloc(void* ptr, size_t size)
+{
+ if (bmalloc_get_allocation_size(ptr) >= size)
+ return (void*)ptr;
+
+ return nullptr;
+}
+
+extern "C" size_t bun__bmalloc__size(void* ptr)
+{
+ return bmalloc_get_allocationpub fn isHeapMemory(memory
+ : anytype) bool
+ {
+ if (comptime use_mimalloc) {
+ const Memory = @TypeOf(memory);
+ if (comptime std.meta.trait.isSingleItemPtr(Memory)) {
+ return Mimalloc.mi_is_in_heap_region(memory);
+ }
+ return Mimalloc.mi_is_in_heap_region(std.mem.sliceAsBytes(memory).ptr);
+ }
+ return false;
+ }
+ _size(ptr);
+}
extern "C" double WTF__parseDouble(const LChar* string, size_t length, size_t* position)
{
diff --git a/src/bun.zig b/src/bun.zig
index 8dd888b69..bfe6cc047 100644
--- a/src/bun.zig
+++ b/src/bun.zig
@@ -3,10 +3,7 @@ pub const Environment = @import("env.zig");
pub const use_mimalloc = !Environment.isTest;
-pub const default_allocator: std.mem.Allocator = if (!use_mimalloc)
- std.heap.c_allocator
-else
- @import("./memory_allocator.zig").c_allocator;
+pub const default_allocator: std.mem.Allocator = @import("./bmalloc_allocator.zig").c_allocator;
pub const huge_allocator: std.mem.Allocator = if (!use_mimalloc)
std.heap.c_allocator
@@ -667,18 +664,8 @@ pub fn once(comptime function: anytype, comptime ReturnType: type) ReturnType {
return Result.execute();
}
-
-pub fn isHeapMemory(memory: anytype) bool {
- if (comptime use_mimalloc) {
- const Memory = @TypeOf(memory);
- if (comptime std.meta.trait.isSingleItemPtr(Memory)) {
- return Mimalloc.mi_is_in_heap_region(memory);
- }
- return Mimalloc.mi_is_in_heap_region(std.mem.sliceAsBytes(memory).ptr);
- }
- return false;
-}
-
+pub const free = @import("./bmalloc_allocator.zig").free;
+pub const bmalloc = @import("./bmalloc_allocator.zig").bmalloc;
pub const Mimalloc = @import("./allocators/mimalloc.zig");
pub inline fn isSliceInBuffer(slice: []const u8, buffer: []const u8) bool {
diff --git a/src/bun_js.zig b/src/bun_js.zig
index 79f1c2596..8763f9960 100644
--- a/src/bun_js.zig
+++ b/src/bun_js.zig
@@ -145,7 +145,7 @@ pub const Run = struct {
run = .{
.vm = try VirtualMachine.init(
- arena.allocator(),
+ bun.default_allocator,
ctx.args,
null,
ctx.log,
@@ -163,7 +163,7 @@ pub const Run = struct {
vm.preload = ctx.preloads;
vm.argv = ctx.passthrough;
vm.arena = &run.arena;
- vm.allocator = arena.allocator();
+ vm.allocator = bun.default_allocator;
b.options.install = ctx.install;
b.resolver.opts.install = ctx.install;
diff --git a/src/cli.zig b/src/cli.zig
index 1debd9254..a35b583b1 100644
--- a/src/cli.zig
+++ b/src/cli.zig
@@ -1030,6 +1030,7 @@ pub const Command = struct {
}
};
+ extern fn bun__bmalloc__init() void;
pub fn which() Tag {
var args_iter = ArgsIterator{ .buf = std.os.argv };
// first one is the executable name
@@ -1153,6 +1154,8 @@ pub const Command = struct {
// _ = BunxCommand;
}
+ bun__bmalloc__init();
+
if (try bun.StandaloneModuleGraph.fromExecutable(bun.default_allocator)) |graph| {
var ctx = Command.Context{
.args = std.mem.zeroes(Api.TransformOptions),
diff --git a/src/http_client_async.zig b/src/http_client_async.zig
index d49f7814d..c6132d100 100644
--- a/src/http_client_async.zig
+++ b/src/http_client_async.zig
@@ -35,8 +35,7 @@ const uws = bun.uws;
pub const MimeType = @import("./http/mime_type.zig");
pub const URLPath = @import("./http/url_path.zig");
// This becomes Arena.allocator
-pub var default_allocator: std.mem.Allocator = undefined;
-var default_arena: Arena = undefined;
+pub const default_allocator = bun.default_allocator;
pub var http_thread: HTTPThread = undefined;
const HiveArray = @import("./hive_array.zig").HiveArray;
const Batch = NetworkThread.Batch;
@@ -627,8 +626,7 @@ pub const HTTPThread = struct {
pub fn onStart(_: FakeStruct) void {
Output.Source.configureNamedThread("HTTP Client");
- default_arena = Arena.init() catch unreachable;
- default_allocator = default_arena.allocator();
+
var loop = uws.Loop.create(struct {
pub fn wakeup(_: *uws.Loop) callconv(.C) void {
http_thread.drainEvents();
@@ -869,7 +867,7 @@ pub inline fn getAllocator() std.mem.Allocator {
}
pub inline fn cleanup(force: bool) void {
- default_arena.gc(force);
+ _ = force;
}
pub const Headers = @import("./http/headers.zig");
@@ -2475,15 +2473,6 @@ pub fn done(this: *HTTPClient, comptime is_ssl: bool, ctx: *NewHTTPContext(is_ss
this.state.request_stage = .done;
this.state.stage = .done;
this.proxy_tunneling = false;
- if (comptime print_every > 0) {
- print_every_i += 1;
- if (print_every_i % print_every == 0) {
- Output.prettyln("Heap stats for HTTP thread\n", .{});
- Output.flush();
- default_arena.dumpThreadStats();
- print_every_i = 0;
- }
- }
callback.run(result);
}
}