Merge pull request #77 from jetzig-framework/arena-pool

Use http.zig arena pool
This commit is contained in:
bobf 2024-05-26 22:05:08 +01:00 committed by GitHub
commit 816367395b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 34 additions and 35 deletions

View File

@ -115,6 +115,9 @@ pub fn jetzigInit(b: *std.Build, exe: *std.Build.Step.Compile, options: JetzigIn
const target = b.host;
const optimize = exe.root_module.optimize orelse .Debug;
if (optimize != .Debug) exe.linkLibC();
const jetzig_dep = b.dependency(
"jetzig",
.{ .optimize = optimize, .target = target },

View File

@ -23,8 +23,8 @@
.hash = "1220d4f1c2472769b0d689ea878f41f0a66cb07f28569a138aea2c0a648a5c90dd4e",
},
.httpz = .{
.url = "https://github.com/karlseguin/http.zig/archive/4ed728d21999ffcb11cc0b0604dcebc9e02cfc17.tar.gz",
.hash = "122010547ef8bbc781372311b66ce72b297c4e61e3423437825da076055ff9c07bb4",
.url = "https://github.com/karlseguin/http.zig/archive/f3ad561fd23262c3f9b8081ff7bb8a5ded0e74bd.tar.gz",
.hash = "1220ea0d5860657d59cf1ca0fe0e553bfabc7d9cd467005488155baffb1ddf65ecf2",
},
},

View File

@ -1,4 +1,5 @@
const std = @import("std");
const builtin = @import("builtin");
const jetzig = @import("jetzig");
const zmd = @import("zmd");
@ -163,8 +164,8 @@ pub const jetzig_options = struct {
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer std.debug.assert(gpa.deinit() == .ok);
const allocator = gpa.allocator();
const allocator = if (builtin.mode == .Debug) gpa.allocator() else std.heap.c_allocator;
defer if (builtin.mode == .Debug) std.debug.assert(gpa.deinit() == .ok);
const app = try jetzig.init(allocator);
defer app.deinit();

View File

@ -98,6 +98,19 @@ pub const config = struct {
/// freed instead of recycled.
pub const max_log_pool_len: usize = 256;
/// Number of request threads. Defaults to number of detected CPUs.
pub const thread_count: ?u16 = null;
/// Number of response worker threads.
pub const worker_count: u16 = 4;
/// Total number of connections managed by worker threads.
pub const max_connections: u16 = 512;
/// The size of each item in the available memory pool used by requests for rendering.
/// Total retained allocation: `worker_count * max_connections`.
pub const arena_size: usize = 1024 * 1024;
/// Path relative to cwd() to serve public content from. Symlinks are not followed.
pub const public_content_path = "public";

View File

@ -141,23 +141,8 @@ pub fn process(self: *Request) !void {
self.processed = true;
}
pub const CallbackState = struct {
arena: *std.heap.ArenaAllocator,
allocator: std.mem.Allocator,
};
pub fn responseCompleteCallback(ptr: *anyopaque) void {
var state: *CallbackState = @ptrCast(@alignCast(ptr));
state.arena.deinit();
state.allocator.destroy(state.arena);
state.allocator.destroy(state);
}
/// Set response headers, write response payload, and finalize the response.
pub fn respond(
self: *Request,
state: *CallbackState,
) !void {
pub fn respond(self: *Request) !void {
if (!self.processed) unreachable;
try self.setCookieHeaders();
@ -165,7 +150,6 @@ pub fn respond(
const status = jetzig.http.status_codes.get(self.response.status_code);
self.httpz_response.status = try status.getCodeInt();
self.httpz_response.body = self.response.content;
self.httpz_response.callback(responseCompleteCallback, @ptrCast(state));
}
/// Render a response. This function can only be called once per request (repeat calls will

View File

@ -81,7 +81,14 @@ pub fn listen(self: *Server) !void {
.{
.port = self.options.port,
.address = self.options.bind,
.thread_pool = .{ .count = @intCast(try std.Thread.getCpuCount()) },
.thread_pool = .{
.count = jetzig.config.get(?u16, "thread_count") orelse @intCast(try std.Thread.getCpuCount()),
},
.workers = .{
.count = jetzig.config.get(u16, "worker_count"),
.max_conn = jetzig.config.get(u16, "max_connections"),
.retain_allocated_bytes = jetzig.config.get(usize, "arena_size"),
},
},
Dispatcher{ .server = self },
);
@ -112,18 +119,7 @@ fn processNextRequest(
) !void {
const start_time = std.time.nanoTimestamp();
const state = try self.allocator.create(jetzig.http.Request.CallbackState);
const arena = try self.allocator.create(std.heap.ArenaAllocator);
arena.* = std.heap.ArenaAllocator.init(self.allocator);
state.* = .{
.arena = arena,
.allocator = self.allocator,
};
// Regular arena deinit occurs in jetzig.http.Request.responseCompletCallback
errdefer state.arena.deinit();
const allocator = state.arena.allocator();
const allocator = httpz_request.arena;
var response = try jetzig.http.Response.init(allocator, httpz_response);
var request = try jetzig.http.Request.init(
@ -144,7 +140,7 @@ fn processNextRequest(
try jetzig.http.middleware.beforeResponse(&middleware_data, &request);
try request.respond(state);
try request.respond();
try jetzig.http.middleware.afterResponse(&middleware_data, &request);
jetzig.http.middleware.deinit(&middleware_data, &request);

View File

@ -56,6 +56,8 @@ pub fn log(
/// Log a one-liner including response status code, path, method, duration, etc.
pub fn logRequest(self: DevelopmentLogger, request: *const jetzig.http.Request) !void {
if (@intFromEnum(LogLevel.INFO) < @intFromEnum(self.level)) return;
var duration_buf: [256]u8 = undefined;
const formatted_duration = try jetzig.colors.duration(
&duration_buf,