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>
This commit is contained in:
Jarred Sumner
2023-07-30 23:51:43 -07:00
committed by GitHub
parent 2ea7290172
commit 9ecae59bbb
16 changed files with 256 additions and 130 deletions

View File

@@ -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(),