aboutsummaryrefslogtreecommitdiff
path: root/src/string.zig
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2023-07-30 23:51:43 -0700
committerGravatar GitHub <noreply@github.com> 2023-07-30 23:51:43 -0700
commit9ecae59bbb1a302977afa94fd879a0c6f8d6195f (patch)
tree7bfff6d9c3264b8d1fce85f63891a1f3e5833a52 /src/string.zig
parent2ea7290172da21f4a9cd58232bf9c1ea0997d6e2 (diff)
downloadbun-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.zig52
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(),