Move call/control of gc_hint to browser.

It has more context than the env about when this should be called. Specifically
it can be called once per session, whereas, in the env, we can only call it
once per context - which could be too often.
This commit is contained in:
Karl Seguin
2025-05-08 18:30:44 +08:00
parent 17ed502123
commit 54a7df8d40
2 changed files with 18 additions and 23 deletions

View File

@@ -60,9 +60,7 @@ pub const Browser = struct {
pub fn init(app: *App) !Browser { pub fn init(app: *App) !Browser {
const allocator = app.allocator; const allocator = app.allocator;
const env = try Env.init(allocator, .{ const env = try Env.init(allocator, .{});
.gc_hints = app.config.gc_hints,
});
errdefer env.deinit(); errdefer env.deinit();
const notification = try Notification.init(allocator, app.notification); const notification = try Notification.init(allocator, app.notification);
@@ -98,6 +96,9 @@ pub const Browser = struct {
if (self.session) |*session| { if (self.session) |*session| {
session.deinit(); session.deinit();
self.session = null; self.session = null;
if (self.app.config.gc_hints) {
self.env.lowMemoryNotification();
}
} }
} }

View File

@@ -174,18 +174,13 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
// index. // index.
prototype_lookup: [Types.len]u16, prototype_lookup: [Types.len]u16,
// Send a lowMemoryNotification whenever we stop an executor
gc_hints: bool,
const Self = @This(); const Self = @This();
const TYPE_LOOKUP = TypeLookup{}; const TYPE_LOOKUP = TypeLookup{};
const Opts = struct { const Opts = struct {};
gc_hints: bool = false,
};
pub fn init(allocator: Allocator, opts: Opts) !*Self { pub fn init(allocator: Allocator, _: Opts) !*Self {
// var params = v8.initCreateParams(); // var params = v8.initCreateParams();
var params = try allocator.create(v8.CreateParams); var params = try allocator.create(v8.CreateParams);
errdefer allocator.destroy(params); errdefer allocator.destroy(params);
@@ -213,7 +208,6 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
.templates = undefined, .templates = undefined,
.allocator = allocator, .allocator = allocator,
.isolate_params = params, .isolate_params = params,
.gc_hints = opts.gc_hints,
.prototype_lookup = undefined, .prototype_lookup = undefined,
}; };
@@ -274,6 +268,18 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
}; };
} }
// V8 doesn't immediately free memory associated with
// a Context, it's managed by the garbage collector. So, when the
// `gc_hints` option is enabled, we'll use the `lowMemoryNotification`
// call on the isolate to encourage v8 to free any contexts which
// have been freed.
pub fn lowMemoryNotification(self: *Self) void {
var handle_scope: v8.HandleScope = undefined;
v8.HandleScope.init(&handle_scope, self.isolate);
defer handle_scope.deinit();
self.isolate.lowMemoryNotification();
}
pub const Executor = struct { pub const Executor = struct {
env: *Self, env: *Self,
@@ -304,18 +310,6 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
self.endScope(); self.endScope();
} }
// V8 doesn't immediately free memory associated with
// a Context, it's managed by the garbage collector. So, when the
// `gc_hints` option is enabled, we'll use the `lowMemoryNotification`
// call on the isolate to encourage v8 to free any contexts which
// have been freed.
if (self.env.gc_hints) {
var handle_scope: v8.HandleScope = undefined;
v8.HandleScope.init(&handle_scope, self.env.isolate);
defer handle_scope.deinit();
self.env.isolate.lowMemoryNotification(); // TODO we only need to call this for the main World Executor
}
self.call_arena.deinit(); self.call_arena.deinit();
self.scope_arena.deinit(); self.scope_arena.deinit();
} }