Skip to content

Commit f786fb5

Browse files
authored
Httpz improvements (#9452)
1 parent 4056dc9 commit f786fb5

File tree

3 files changed

+106
-7
lines changed

3 files changed

+106
-7
lines changed

frameworks/Zig/httpz/run.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
echo "Waiting for Httpz framework to start..."
22

3-
httpz
3+
httpz 3000

frameworks/Zig/httpz/src/main.zig

Lines changed: 104 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,109 @@ pub fn main() !void {
3131
.prng = &prng,
3232
};
3333

34-
server = try httpz.ServerApp(*endpoints.Global).init(allocator, .{ .port = 3000, .address = "0.0.0.0", .workers = .{
35-
.count = @truncate(cpu_count),
36-
.max_conn = 4096,
37-
}, .thread_pool = .{ .count = @truncate(cpu_count * 2) } }, &global);
34+
var httpz_port: []u8 = undefined;
35+
var arg_string = try std.fmt.allocPrint(allocator, "{s}", .{"0"});
36+
defer allocator.free(arg_string);
37+
38+
var args = try std.process.argsWithAllocator(allocator);
39+
defer args.deinit();
40+
while (args.next()) |arg| {
41+
arg_string = try std.fmt.allocPrint(allocator, "{s}", .{arg});
42+
43+
httpz_port = arg_string; // use arg
44+
}
45+
46+
var port = try std.fmt.parseInt(u16,httpz_port, 0);
47+
48+
if (port == 0) {
49+
port = 3000;
50+
}
51+
52+
const workers = @as(u16, @intCast(16 * cpu_count));
53+
54+
server = try httpz.ServerApp(*endpoints.Global).init(allocator, .{
55+
.port = port,
56+
.address = "0.0.0.0",
57+
.workers = .{
58+
// Number of worker threads
59+
// (blocking mode: handled differently)
60+
.count = workers,
61+
62+
// Maximum number of concurrent connection each worker can handle
63+
// (blocking mode: currently ignored)
64+
.max_conn = 8_192,
65+
66+
// Minimum number of connection states each worker should maintain
67+
// (blocking mode: currently ignored)
68+
.min_conn = 64,
69+
70+
// A pool of larger buffers that can be used for any data larger than configured
71+
// static buffers. For example, if response headers don't fit in in
72+
// $response.header_buffer_size, a buffer will be pulled from here.
73+
// This is per-worker.
74+
.large_buffer_count = 16,
75+
76+
// The size of each large buffer.
77+
.large_buffer_size = 65536,
78+
79+
// Size of bytes retained for the connection arena between use. This will
80+
// result in up to `count * min_conn * retain_allocated_bytes` of memory usage.
81+
.retain_allocated_bytes = 4096,
82+
},
83+
84+
// configures the threadpool which processes requests. The threadpool is
85+
// where your application code runs.
86+
.thread_pool = .{
87+
// Number threads. If you're handlers are doing a lot of i/o, a higher
88+
// number might provide better throughput
89+
// (blocking mode: handled differently)
90+
.count = 256,
91+
92+
// The maximum number of pending requests that the thread pool will accept
93+
// This applies back pressure to the above workers and ensures that, under load
94+
// pending requests get precedence over processing new requests.
95+
.backlog = 2048,
96+
97+
// Size of the static buffer to give each thread. Memory usage will be
98+
// `count * buffer_size`. If you're making heavy use of either `req.arena` or
99+
// `res.arena`, this is likely the single easiest way to gain performance.
100+
.buffer_size = 8192,
101+
},
102+
.request = .{
103+
// Maximum request body size that we'll process. We can allocate up
104+
// to this much memory per request for the body. Internally, we might
105+
// keep this memory around for a number of requests as an optimization.
106+
.max_body_size = 1_048_576,
107+
108+
// This memory is allocated upfront. The request header _must_ fit into
109+
// this space, else the request will be rejected.
110+
.buffer_size = 4_096,
111+
112+
// Maximum number of headers to accept.
113+
// Additional headers will be silently ignored.
114+
.max_header_count = 32,
115+
116+
// Maximum number of URL parameters to accept.
117+
// Additional parameters will be silently ignored.
118+
.max_param_count = 10,
119+
120+
// Maximum number of query string parameters to accept.
121+
// Additional parameters will be silently ignored.
122+
.max_query_count = 32,
123+
124+
// Maximum number of x-www-form-urlencoded fields to support.
125+
// Additional parameters will be silently ignored. This must be
126+
// set to a value greater than 0 (the default) if you're going
127+
// to use the req.formData() method.
128+
.max_form_count = 0,
129+
130+
// Maximum number of multipart/form-data fields to support.
131+
// Additional parameters will be silently ignored. This must be
132+
// set to a value greater than 0 (the default) if you're going
133+
// to use the req.multiFormData() method.
134+
.max_multiform_count = 0,
135+
},
136+
}, &global);
38137
defer server.deinit();
39138

40139
// now that our server is up, we register our intent to handle SIGINT
@@ -50,7 +149,7 @@ pub fn main() !void {
50149
router.get("/db", endpoints.db);
51150
router.get("/fortunes", endpoints.fortune);
52151

53-
std.debug.print("Httpz listening at 0.0.0.0:{d}\n", .{3000});
152+
std.debug.print("Httpz using {d} workers listening at 0.0.0.0:{d}\n", .{ workers, port });
54153

55154
try server.listen();
56155
}

frameworks/Zig/httpz/src/pool.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub fn initPool(allocator: Allocator) !*pg.Pool {
1111
//std.debug.print("Connection: {s}:{s}@{s}:{d}/{s}\n", .{ info.username, info.password, info.hostname, info.port, info.database });
1212

1313
const pg_pool = try Pool.init(allocator, .{
14-
.size = 28,
14+
.size = 56,
1515
.connect = .{
1616
.port = info.port,
1717
.host = info.hostname,

0 commit comments

Comments
 (0)