|
@@ -31,10 +31,109 @@ pub fn main() !void {
|
|
|
.prng = &prng,
|
|
|
};
|
|
|
|
|
|
- server = try httpz.ServerApp(*endpoints.Global).init(allocator, .{ .port = 3000, .address = "0.0.0.0", .workers = .{
|
|
|
- .count = @truncate(cpu_count),
|
|
|
- .max_conn = 4096,
|
|
|
- }, .thread_pool = .{ .count = @truncate(cpu_count * 2) } }, &global);
|
|
|
+ var httpz_port: []u8 = undefined;
|
|
|
+ var arg_string = try std.fmt.allocPrint(allocator, "{s}", .{"0"});
|
|
|
+ defer allocator.free(arg_string);
|
|
|
+
|
|
|
+ var args = try std.process.argsWithAllocator(allocator);
|
|
|
+ defer args.deinit();
|
|
|
+ while (args.next()) |arg| {
|
|
|
+ arg_string = try std.fmt.allocPrint(allocator, "{s}", .{arg});
|
|
|
+
|
|
|
+ httpz_port = arg_string; // use arg
|
|
|
+ }
|
|
|
+
|
|
|
+ var port = try std.fmt.parseInt(u16,httpz_port, 0);
|
|
|
+
|
|
|
+ if (port == 0) {
|
|
|
+ port = 3000;
|
|
|
+ }
|
|
|
+
|
|
|
+ const workers = @as(u16, @intCast(16 * cpu_count));
|
|
|
+
|
|
|
+ server = try httpz.ServerApp(*endpoints.Global).init(allocator, .{
|
|
|
+ .port = port,
|
|
|
+ .address = "0.0.0.0",
|
|
|
+ .workers = .{
|
|
|
+ // Number of worker threads
|
|
|
+ // (blocking mode: handled differently)
|
|
|
+ .count = workers,
|
|
|
+
|
|
|
+ // Maximum number of concurrent connection each worker can handle
|
|
|
+ // (blocking mode: currently ignored)
|
|
|
+ .max_conn = 8_192,
|
|
|
+
|
|
|
+ // Minimum number of connection states each worker should maintain
|
|
|
+ // (blocking mode: currently ignored)
|
|
|
+ .min_conn = 64,
|
|
|
+
|
|
|
+ // A pool of larger buffers that can be used for any data larger than configured
|
|
|
+ // static buffers. For example, if response headers don't fit in in
|
|
|
+ // $response.header_buffer_size, a buffer will be pulled from here.
|
|
|
+ // This is per-worker.
|
|
|
+ .large_buffer_count = 16,
|
|
|
+
|
|
|
+ // The size of each large buffer.
|
|
|
+ .large_buffer_size = 65536,
|
|
|
+
|
|
|
+ // Size of bytes retained for the connection arena between use. This will
|
|
|
+ // result in up to `count * min_conn * retain_allocated_bytes` of memory usage.
|
|
|
+ .retain_allocated_bytes = 4096,
|
|
|
+ },
|
|
|
+
|
|
|
+ // configures the threadpool which processes requests. The threadpool is
|
|
|
+ // where your application code runs.
|
|
|
+ .thread_pool = .{
|
|
|
+ // Number threads. If you're handlers are doing a lot of i/o, a higher
|
|
|
+ // number might provide better throughput
|
|
|
+ // (blocking mode: handled differently)
|
|
|
+ .count = 256,
|
|
|
+
|
|
|
+ // The maximum number of pending requests that the thread pool will accept
|
|
|
+ // This applies back pressure to the above workers and ensures that, under load
|
|
|
+ // pending requests get precedence over processing new requests.
|
|
|
+ .backlog = 2048,
|
|
|
+
|
|
|
+ // Size of the static buffer to give each thread. Memory usage will be
|
|
|
+ // `count * buffer_size`. If you're making heavy use of either `req.arena` or
|
|
|
+ // `res.arena`, this is likely the single easiest way to gain performance.
|
|
|
+ .buffer_size = 8192,
|
|
|
+ },
|
|
|
+ .request = .{
|
|
|
+ // Maximum request body size that we'll process. We can allocate up
|
|
|
+ // to this much memory per request for the body. Internally, we might
|
|
|
+ // keep this memory around for a number of requests as an optimization.
|
|
|
+ .max_body_size = 1_048_576,
|
|
|
+
|
|
|
+ // This memory is allocated upfront. The request header _must_ fit into
|
|
|
+ // this space, else the request will be rejected.
|
|
|
+ .buffer_size = 4_096,
|
|
|
+
|
|
|
+ // Maximum number of headers to accept.
|
|
|
+ // Additional headers will be silently ignored.
|
|
|
+ .max_header_count = 32,
|
|
|
+
|
|
|
+ // Maximum number of URL parameters to accept.
|
|
|
+ // Additional parameters will be silently ignored.
|
|
|
+ .max_param_count = 10,
|
|
|
+
|
|
|
+ // Maximum number of query string parameters to accept.
|
|
|
+ // Additional parameters will be silently ignored.
|
|
|
+ .max_query_count = 32,
|
|
|
+
|
|
|
+ // Maximum number of x-www-form-urlencoded fields to support.
|
|
|
+ // Additional parameters will be silently ignored. This must be
|
|
|
+ // set to a value greater than 0 (the default) if you're going
|
|
|
+ // to use the req.formData() method.
|
|
|
+ .max_form_count = 0,
|
|
|
+
|
|
|
+ // Maximum number of multipart/form-data fields to support.
|
|
|
+ // Additional parameters will be silently ignored. This must be
|
|
|
+ // set to a value greater than 0 (the default) if you're going
|
|
|
+ // to use the req.multiFormData() method.
|
|
|
+ .max_multiform_count = 0,
|
|
|
+ },
|
|
|
+ }, &global);
|
|
|
defer server.deinit();
|
|
|
|
|
|
// now that our server is up, we register our intent to handle SIGINT
|
|
@@ -50,7 +149,7 @@ pub fn main() !void {
|
|
|
router.get("/db", endpoints.db);
|
|
|
router.get("/fortunes", endpoints.fortune);
|
|
|
|
|
|
- std.debug.print("Httpz listening at 0.0.0.0:{d}\n", .{3000});
|
|
|
+ std.debug.print("Httpz using {d} workers listening at 0.0.0.0:{d}\n", .{ workers, port });
|
|
|
|
|
|
try server.listen();
|
|
|
}
|