Browse Source

Httpz improvements (#9452)

Dragos Varovici 8 months ago
parent
commit
f786fb570f
3 changed files with 106 additions and 7 deletions
  1. 1 1
      frameworks/Zig/httpz/run.sh
  2. 104 5
      frameworks/Zig/httpz/src/main.zig
  3. 1 1
      frameworks/Zig/httpz/src/pool.zig

+ 1 - 1
frameworks/Zig/httpz/run.sh

@@ -1,3 +1,3 @@
 echo "Waiting for Httpz framework to start..."
 
-httpz
+httpz 3000

+ 104 - 5
frameworks/Zig/httpz/src/main.zig

@@ -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();
 }

+ 1 - 1
frameworks/Zig/httpz/src/pool.zig

@@ -11,7 +11,7 @@ pub fn initPool(allocator: Allocator) !*pg.Pool {
     //std.debug.print("Connection: {s}:{s}@{s}:{d}/{s}\n", .{ info.username, info.password, info.hostname, info.port, info.database });
 
     const pg_pool = try Pool.init(allocator, .{
-        .size = 28,
+        .size = 56,
         .connect = .{
             .port = info.port,
             .host = info.hostname,