Compare commits

...

3 Commits

Author SHA1 Message Date
autofix-ci[bot]
ceed778ffe [autofix.ci] apply automated fixes 2025-08-04 03:52:47 +00:00
Jarred Sumner
2e07c23d0d Update h2_frame_parser.zig 2025-08-03 20:48:19 -07:00
Jarred Sumner
b58482b3ab Report H2FrameParser memory cost more precisely 2025-08-03 20:44:07 -07:00
4 changed files with 61 additions and 12 deletions

View File

@@ -767,6 +767,14 @@ pub const H2FrameParser = struct {
front: usize = 0,
len: usize = 0,
pub fn memoryCost(this: *const PendingQueue) usize {
var counter: usize = @sizeOf(PendingQueue);
for (this.data.items) |*item| {
counter += item.memoryCost();
}
return counter;
}
pub fn deinit(self: *PendingQueue, allocator: Allocator) void {
self.front = 0;
self.len = 0;
@@ -847,8 +855,20 @@ pub const H2FrameParser = struct {
pub fn slice(this: *const PendingFrame) []u8 {
return this.buffer[this.offset..this.len];
}
pub fn memoryCost(this: *const PendingFrame) usize {
var counter: usize = @sizeOf(PendingFrame);
counter += this.buffer.len;
return counter;
}
};
pub fn memoryCost(this: *const Stream) usize {
var counter: usize = @sizeOf(Stream);
counter += this.dataFrameQueue.memoryCost();
return counter;
}
pub fn getPadding(
this: *Stream,
frameLen: usize,
@@ -1714,6 +1734,18 @@ pub const H2FrameParser = struct {
}
}
pub fn memoryCost(this: *H2FrameParser) usize {
var counter: usize = @sizeOf(H2FrameParser);
counter += this.writeBuffer.memoryCost();
counter += this.readBuffer.memoryCost();
counter += this.streams.capacity() * @sizeOf(u32);
var iter = this.streams.valueIterator();
while (iter.next()) |stream| {
counter += stream.memoryCost();
}
return counter;
}
fn registerAutoFlush(this: *H2FrameParser) void {
if (this.auto_flusher.registered) return;
this.ref();
@@ -4414,10 +4446,6 @@ pub const H2FrameParser = struct {
}
pub fn detachFromJS(this: *H2FrameParser, _: *jsc.JSGlobalObject, _: *jsc.CallFrame) bun.JSError!JSValue {
jsc.markBinding(@src());
var it = this.streams.valueIterator();
while (it.next()) |stream| {
stream.freeResources(this, false);
}
this.detach();
if (this.strong_this.tryGet()) |this_value| {
js.gc.context.clear(this_value, this.globalThis);
@@ -4444,6 +4472,18 @@ pub const H2FrameParser = struct {
hpack.deinit();
this.hpack = null;
}
this.deinitStreams();
}
fn deinitStreams(this: *H2FrameParser) void {
var it = this.streams.valueIterator();
while (it.next()) |stream| {
stream.freeResources(this, true);
}
var streams = this.streams;
defer streams.deinit();
this.streams = bun.U32HashMap(Stream).init(bun.default_allocator);
}
fn deinit(this: *H2FrameParser) void {
@@ -4458,18 +4498,12 @@ pub const H2FrameParser = struct {
}
this.detach();
this.strong_this.deinit();
var it = this.streams.valueIterator();
while (it.next()) |stream| {
stream.freeResources(this, true);
}
var streams = this.streams;
defer streams.deinit();
this.streams = bun.U32HashMap(Stream).init(bun.default_allocator);
}
pub fn finalize(this: *H2FrameParser) void {
log("finalize", .{});
this.strong_this.deinit();
this.deinitStreams();
this.deref();
}
};

View File

@@ -125,6 +125,7 @@ export default [
finalize: true,
construct: true,
constructNeedsThis: true,
memoryCost: true,
klass: {},
values: [
"context",

View File

@@ -22,6 +22,10 @@ pub fn isEmpty(this: *const MutableString) bool {
return this.list.items.len == 0;
}
pub fn memoryCost(this: *const MutableString) usize {
return this.list.capacity;
}
pub fn deinit(str: *MutableString) void {
if (str.list.capacity > 0) {
str.list.expandToCapacity();

View File

@@ -1,3 +1,4 @@
import { estimateShallowMemoryUsageOf } from "bun:jsc";
import { bunEnv, bunExe, isCI, nodeExe } from "harness";
import { createTest } from "node-harness";
import fs from "node:fs";
@@ -10,6 +11,11 @@ import { Duplex } from "stream";
import http2utils from "./helpers";
import { nodeEchoServer, TLS_CERT, TLS_OPTIONS } from "./http2-helpers";
const { afterEach, beforeEach, describe, expect, it, createCallCheckCtx } = createTest(import.meta.path);
function getMemorySize(obj) {
return estimateShallowMemoryUsageOf(obj[Symbol.for("::bunhttp2native::")]);
}
function invalidArgTypeHelper(input) {
if (input === null) return " Received null";
@@ -1666,8 +1672,9 @@ it("http2 server handles multiple concurrent requests", async () => {
server.on("listening", () => {
const port = server.address().port;
const client = http2.connect(`http://localhost:${port}`);
const client = http2.connect(`http://localhost:${port}`);
const initialMemorySize = getMemorySize(client);
client.setMaxListeners(101);
client.on("goaway", console.log);
@@ -1700,6 +1707,9 @@ it("http2 server handles multiple concurrent requests", async () => {
req.on("data", d => (data += d));
req.on("end", () => {
// Test that memoryCost() works.
expect(getMemorySize(client)).toBeGreaterThan(initialMemorySize);
expect(body).toBe(data);
});