mirror of
https://github.com/oven-sh/bun
synced 2026-02-14 12:51:54 +00:00
perf: use jsonStringifyFast for faster JSON serialization (#25733)
## Summary Apply the same optimization technique from PR #25717 (Response.json) to other APIs that use JSON.stringify internally: - **IPC message serialization** (`ipc.zig`) - used for inter-process communication - **console.log with %j format** (`ConsoleObject.zig`) - commonly used for debugging - **PostgreSQL JSON/JSONB types** (`PostgresRequest.zig`) - database operations - **MySQL JSON type** (`MySQLTypes.zig`) - database operations - **Jest %j/%o format specifiers** (`jest.zig`) - test output formatting - **Transpiler tsconfig/macros** (`JSTranspiler.zig`) - build configuration ### Root Cause When calling `JSONStringify(globalObject, value, 0)`, the space parameter `0` becomes `jsNumber(0)`, which is NOT `undefined`. This causes JSC's FastStringifier (SIMD-optimized) to bail out: ```cpp // In WebKit's JSONObject.cpp FastStringifier::stringify() if (!space.isUndefined()) { logOutcome("space"_s); return { }; // Bail out to slow path } ``` Using `jsonStringifyFast` which passes `jsUndefined()` triggers the fast path. ### Expected Performance Improvement Based on PR #25717 results, these changes should provide ~3x speedup for JSON serialization in the affected APIs. ## Test plan - [x] Debug build compiles successfully - [x] Basic functionality verified (IPC, console.log %j, Response.json) - [x] Existing tests pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1629,11 +1629,11 @@ pub const Formatter = struct {
|
||||
},
|
||||
|
||||
.j => {
|
||||
// JSON.stringify the value
|
||||
// JSON.stringify the value using FastStringifier for SIMD optimization
|
||||
var str = bun.String.empty;
|
||||
defer str.deref();
|
||||
|
||||
try next_value.jsonStringify(global, 0, &str);
|
||||
try next_value.jsonStringifyFast(global, &str);
|
||||
this.addForNewLine(str.length());
|
||||
writer.print("{f}", .{str});
|
||||
},
|
||||
|
||||
@@ -165,7 +165,8 @@ pub const Config = struct {
|
||||
}
|
||||
|
||||
if (!kind.isStringLike()) {
|
||||
try tsconfig.jsonStringify(globalThis, 0, &out);
|
||||
// Use jsonStringifyFast for SIMD-optimized serialization
|
||||
try tsconfig.jsonStringifyFast(globalThis, &out);
|
||||
} else {
|
||||
out = try tsconfig.toBunString(globalThis);
|
||||
}
|
||||
@@ -204,7 +205,8 @@ pub const Config = struct {
|
||||
defer out.deref();
|
||||
// TODO: write a converter between JSC types and Bun AST types
|
||||
if (is_object) {
|
||||
try macros.jsonStringify(globalThis, 0, &out);
|
||||
// Use jsonStringifyFast for SIMD-optimized serialization
|
||||
try macros.jsonStringifyFast(globalThis, &out);
|
||||
} else {
|
||||
out = try macros.toBunString(globalThis);
|
||||
}
|
||||
|
||||
@@ -229,7 +229,9 @@ const json = struct {
|
||||
|
||||
pub fn serialize(writer: *bun.io.StreamBuffer, global: *jsc.JSGlobalObject, value: JSValue, is_internal: IsInternal) !usize {
|
||||
var out: bun.String = undefined;
|
||||
try value.jsonStringify(global, 0, &out);
|
||||
// Use jsonStringifyFast which passes undefined for the space parameter,
|
||||
// triggering JSC's SIMD-optimized FastStringifier code path.
|
||||
try value.jsonStringifyFast(global, &out);
|
||||
defer out.deref();
|
||||
|
||||
if (out.tag == .Dead) return IPCSerializationError.SerializationFailed;
|
||||
|
||||
@@ -430,7 +430,8 @@ pub fn formatLabel(globalThis: *JSGlobalObject, label: string, function_args: []
|
||||
'j', 'o' => {
|
||||
var str = bun.String.empty;
|
||||
defer str.deref();
|
||||
try current_arg.jsonStringify(globalThis, 0, &str);
|
||||
// Use jsonStringifyFast for SIMD-optimized serialization
|
||||
try current_arg.jsonStringifyFast(globalThis, &str);
|
||||
const owned_slice = bun.handleOom(str.toOwnedSlice(allocator));
|
||||
defer allocator.free(owned_slice);
|
||||
bun.handleOom(list.appendSlice(owned_slice));
|
||||
|
||||
@@ -486,7 +486,8 @@ pub const Value = union(enum) {
|
||||
|
||||
.MYSQL_TYPE_JSON => {
|
||||
var str: bun.String = bun.String.empty;
|
||||
try value.jsonStringify(globalObject, 0, &str);
|
||||
// Use jsonStringifyFast for SIMD-optimized serialization
|
||||
try value.jsonStringifyFast(globalObject, &str);
|
||||
defer str.deref();
|
||||
return Value{ .string = str.toUTF8(bun.default_allocator) };
|
||||
},
|
||||
|
||||
@@ -101,7 +101,8 @@ pub fn writeBind(
|
||||
.jsonb, .json => {
|
||||
var str = bun.String.empty;
|
||||
defer str.deref();
|
||||
try value.jsonStringify(globalObject, 0, &str);
|
||||
// Use jsonStringifyFast for SIMD-optimized serialization
|
||||
try value.jsonStringifyFast(globalObject, &str);
|
||||
const slice = str.toUTF8WithoutRef(bun.default_allocator);
|
||||
defer slice.deinit();
|
||||
const l = try writer.length();
|
||||
|
||||
Reference in New Issue
Block a user