diff options
| author | 2023-07-30 23:51:43 -0700 | |
|---|---|---|
| committer | 2023-07-30 23:51:43 -0700 | |
| commit | 9ecae59bbb1a302977afa94fd879a0c6f8d6195f (patch) | |
| tree | 7bfff6d9c3264b8d1fce85f63891a1f3e5833a52 /src/string.zig | |
| parent | 2ea7290172da21f4a9cd58232bf9c1ea0997d6e2 (diff) | |
| download | bun-9ecae59bbb1a302977afa94fd879a0c6f8d6195f.tar.gz bun-9ecae59bbb1a302977afa94fd879a0c6f8d6195f.tar.zst bun-9ecae59bbb1a302977afa94fd879a0c6f8d6195f.zip | |
Fix memory leak in response.clone(), further reduce memory usage of Request & Response (#3902)
* Atomize respsone.url & response.statusText
* Fix warning
* Atomize Request & Response URLs when possible
* Fix memory leak in response.clone()
bun/bench/snippets on jarred/atomize
❯ mem bun --smol request-response-clone.mjs
cpu: Apple M1 Max
runtime: bun 0.7.2 (arm64-darwin)
benchmark time (avg) (min … max) p75 p99 p995
-------------------------------------------------------- -----------------------------
req.clone().url 77.3 ns/iter (40.35 ns … 222.64 ns) 91.53 ns 128.11 ns 172.78 ns
resp.clone().url 162.43 ns/iter (116 ns … 337.77 ns) 177.4 ns 232.38 ns 262.65 ns
Peak memory usage: 60 MB
bun/bench/snippets on jarred/atomize
❯ mem bun-0.7.1 --smol request-response-clone.mjs
cpu: Apple M1 Max
runtime: bun 0.7.1 (arm64-darwin)
benchmark time (avg) (min … max) p75 p99 p995
-------------------------------------------------------- -----------------------------
req.clone().url 115.85 ns/iter (80.35 ns … 247.39 ns) 128.19 ns 181.93 ns 207.23 ns
resp.clone().url 252.32 ns/iter (202.6 ns … 351.07 ns) 266.56 ns 325.88 ns 334.73 ns
Peak memory usage: 1179 MB
* Update tests
* Update js_ast.zig
* Update test
---------
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'src/string.zig')
| -rw-r--r-- | src/string.zig | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/src/string.zig b/src/string.zig index 1e2ee752e..4fb6e001a 100644 --- a/src/string.zig +++ b/src/string.zig @@ -276,6 +276,10 @@ pub const String = extern struct { extern fn BunString__fromLatin1Unitialized(len: usize) String; extern fn BunString__fromUTF16Unitialized(len: usize) String; + pub fn isGlobal(this: String) bool { + return this.tag == Tag.ZigString and this.value.ZigString.isGloballyAllocated(); + } + pub fn toOwnedSlice(this: String, allocator: std.mem.Allocator) ![]u8 { switch (this.tag) { .ZigString => return try this.value.ZigString.toOwnedSlice(allocator), @@ -339,6 +343,54 @@ pub const String = extern struct { return this; } + pub fn clone(this: String) String { + if (this.tag == .WTFStringImpl) { + return this.dupeRef(); + } + + if (this.isEmpty()) { + return this; + } + + if (this.isUTF16()) { + var new = createUninitializedUTF16(this.length()); + @memcpy(@constCast(new.byteSlice()), this.byteSlice()); + return new; + } + + return create(this.byteSlice()); + } + + extern fn BunString__createAtom(bytes: [*]const u8, len: usize) String; + + /// May return .Dead if the string is too long or non-ascii. + pub fn createAtom(bytes: []const u8) String { + JSC.markBinding(@src()); + return BunString__createAtom(bytes.ptr, bytes.len); + } + + pub fn tryCreateAtom(bytes: []const u8) ?String { + const atom = createAtom(bytes); + if (atom.isEmpty()) { + return null; + } + + return atom; + } + + /// Atomized strings are interned strings + /// They're de-duplicated in a threadlocal hash table + /// They cannot be used from other threads. + pub fn createAtomIfPossible(bytes: []const u8) String { + if (bytes.len < 64) { + if (tryCreateAtom(bytes)) |atom| { + return atom; + } + } + + return create(bytes); + } + pub fn utf8ByteLength(this: String) usize { return switch (this.tag) { .WTFStringImpl => this.value.WTFStringImpl.utf8ByteLength(), |
