diff --git a/bench/snippets/buffer-fill.mjs b/bench/snippets/buffer-fill.mjs new file mode 100644 index 0000000000000..e67e32eb1bef0 --- /dev/null +++ b/bench/snippets/buffer-fill.mjs @@ -0,0 +1,15 @@ +import { bench, run } from "./runner.mjs"; + +for (let size of [32, 2048, 1024 * 16, 1024 * 1024 * 2, 1024 * 1024 * 16]) { + for (let fillSize of [4, 8, 16, 11]) { + const buffer = Buffer.allocUnsafe(size); + + const pattern = "x".repeat(fillSize); + + bench(`Buffer.fill ${size} bytes with ${fillSize} byte value`, () => { + buffer.fill(pattern); + }); + } +} + +await run(); diff --git a/src/bun.js/node/buffer.zig b/src/bun.js/node/buffer.zig index 3a0750f05a05b..86d4fc73c1e90 100644 --- a/src/bun.js/node/buffer.zig +++ b/src/bun.js/node/buffer.zig @@ -1,6 +1,7 @@ const bun = @import("root").bun; const JSC = bun.JSC; const Encoder = JSC.WebCore.Encoder; +const Environment = bun.Environment; pub const BufferVectorized = struct { pub fn fill( @@ -49,23 +50,33 @@ pub const BufferVectorized = struct { } catch return false; switch (written) { - 0 => {}, - 1 => @memset(buf, buf[0]), - else => { - var contents = buf[0..written]; - buf = buf[written..]; + 0 => return true, + 1 => { + @memset(buf, buf[0]); + return true; + }, + inline 4, 8, 16 => |n| if (comptime Environment.isMac) { + const pattern = buf[0..n]; + buf = buf[pattern.len..]; + @field(bun.C, bun.fmt.comptimePrint("memset_pattern{d}", .{n}))(buf.ptr, pattern.ptr, buf.len); + return true; + }, + else => {}, + } - while (buf.len >= contents.len) { - bun.copy(u8, buf, contents); - buf = buf[contents.len..]; - contents.len *= 2; - } + var contents = buf[0..written]; + buf = buf[written..]; - if (buf.len > 0) { - bun.copy(u8, buf, contents[0..buf.len]); - } - }, + while (buf.len >= contents.len) { + bun.copy(u8, buf, contents); + buf = buf[contents.len..]; + contents.len *= 2; } + + if (buf.len > 0) { + bun.copy(u8, buf, contents[0..buf.len]); + } + return true; } }; diff --git a/src/darwin_c.zig b/src/darwin_c.zig index 6771f06ad8bce..2c0268058f8ea 100644 --- a/src/darwin_c.zig +++ b/src/darwin_c.zig @@ -888,3 +888,7 @@ pub const CLOCK_THREAD_CPUTIME_ID = 1; pub const netdb = @cImport({ @cInclude("netdb.h"); }); + +pub extern fn memset_pattern4(buf: [*]u8, pattern: [*]const u8, len: usize) void; +pub extern fn memset_pattern8(buf: [*]u8, pattern: [*]const u8, len: usize) void; +pub extern fn memset_pattern16(buf: [*]u8, pattern: [*]const u8, len: usize) void; diff --git a/test/cli/install/bun-install.test.ts b/test/cli/install/bun-install.test.ts index d88b0aa1fa5e7..1c9ed116268e9 100644 --- a/test/cli/install/bun-install.test.ts +++ b/test/cli/install/bun-install.test.ts @@ -8210,12 +8210,8 @@ it("should ensure read permissions of all extracted files", async () => { await runBunInstall(env, package_dir); - expect((await stat(join(package_dir, "node_modules", "pkg-only-owner", "package.json"))).mode & 0o666).toBe( - isWindows ? 0o666 : 0o644, - ); - expect((await stat(join(package_dir, "node_modules", "pkg-only-owner", "src", "index.js"))).mode & 0o666).toBe( - isWindows ? 0o666 : 0o644, - ); + expect((await stat(join(package_dir, "node_modules", "pkg-only-owner", "package.json"))).mode & 0o444).toBe(0o444); + expect((await stat(join(package_dir, "node_modules", "pkg-only-owner", "src", "index.js"))).mode & 0o444).toBe(0o444); }); it("should handle @scoped name that contains tilde, issue#7045", async () => {