Browse Source

Zap performance improvements (#9293)

Dragos Varovici 10 months ago
parent
commit
19dbe27e1d

+ 13 - 0
frameworks/Zig/zap/build-nginx-conf.sh

@@ -0,0 +1,13 @@
+#!/bin/bash
+
+CPU_COUNT=$(nproc)
+P=3000
+END=$(($P+$CPU_COUNT))
+CONF=""
+
+while [ $P -lt $END ]; do
+  CONF+="\t\tserver 127.0.0.1:$P;\n"
+  let P=P+1
+done
+
+sed -i "s|# replace|$CONF|g" nginx.conf

+ 0 - 19
frameworks/Zig/zap/build.zig

@@ -40,16 +40,13 @@ pub fn build(b: *std.Build) !void {
 
     const zap_module = b.dependency("zap", dep_opts).module("zap");
     const pg_module = b.dependency("pg", dep_opts).module("pg");
-    const dig_module = b.dependency("dig", dep_opts).module("dns");
 
     try modules.put("zap", zap_module);
     try modules.put("pg", pg_module);
-    try modules.put("dig", dig_module);
 
     //     // Expose this as a module that others can import
     exe.root_module.addImport("zap", zap_module);
     exe.root_module.addImport("pg", pg_module);
-    exe.root_module.addImport("dig", dig_module);
 
     exe.linkLibrary(zap.artifact("facil.io"));
 
@@ -80,20 +77,4 @@ pub fn build(b: *std.Build) !void {
     // This will evaluate the `run` step rather than the default, which is "install".
     const run_step = b.step("run", "Run the app");
     run_step.dependOn(&run_cmd.step);
-
-    // Creates a step for unit testing. This only builds the test executable
-    // but does not run it.
-    const unit_tests = b.addTest(.{
-        .root_source_file = b.path("src/main.zig"),
-        .target = target,
-        .optimize = optimize,
-    });
-
-    const run_unit_tests = b.addRunArtifact(unit_tests);
-
-    // Similar to creating the run step earlier, this exposes a `test` step to
-    // the `zig build --help` menu, providing a way for the user to request
-    // running the unit tests.
-    const test_step = b.step("test", "Run unit tests");
-    test_step.dependOn(&run_unit_tests.step);
 }

+ 0 - 1
frameworks/Zig/zap/build.zig.zon

@@ -9,5 +9,4 @@
     },
     .pg = .{ .url = "https://github.com/karlseguin/pg.zig/archive/239a4468163a49d8c0d03285632eabe96003e9e2.tar.gz", 
         .hash = "1220a1d7e51e2fa45e547c76a9e099c09d06e14b0b9bfc6baa89367f56f1ded399a0" },
-    .dig = .{ .url = "https://github.com/lun-4/zigdig/archive/a54c85c26aa83c64ee81e3ee1818890be5cbed0b.tar.gz", .hash = "1220f078ab62d1328339504f9122dc4d241be30ada451628d78b8a3bf5bb9be1dcba" },
 } }

+ 33 - 0
frameworks/Zig/zap/nginx.conf

@@ -0,0 +1,33 @@
+error_log        stderr;
+worker_processes auto;
+
+events {
+  worker_connections 65535;
+  multi_accept       off;
+}
+
+http {
+  default_type          application/octet-stream;
+  client_body_temp_path /tmp;
+  access_log            off;
+
+  sendfile              on;
+  tcp_nopush            on;
+  keepalive_requests    100000;
+  keepalive_timeout     65;
+
+  upstream workers {
+    # replace
+  }
+
+  server {
+    listen      8080;
+    server_name tfb-server;
+
+    location / {
+      proxy_http_version 1.1;
+      proxy_set_header   Connection "";
+      proxy_pass         http://workers;
+    }
+  }
+}

+ 0 - 3
frameworks/Zig/zap/run.sh

@@ -1,3 +0,0 @@
-echo "Waiting for ZAP framework to start..."
-
-zap

+ 15 - 9
frameworks/Zig/zap/src/endpoints.zig

@@ -168,20 +168,28 @@ pub const DbEndpoint = struct {
             }
         }
 
-        // std.debug.print("Attempting to return random: {}\n", .{random_number});
-
         if (random_number == 0) {
             return;
         }
 
-        var conn = pool.acquire() catch return;
-        defer conn.release();
-
-        const row_result = conn.row("SELECT id, randomNumber FROM World WHERE id = $1", .{random_number}) catch |err| {
+        const json_to_send = getJson(pool, random_number) catch |err| {
             std.debug.print("Error querying database: {}\n", .{err});
             return;
         };
+
+        req.sendBody(json_to_send) catch return;
+
+        return;
+    }
+
+    fn getJson(pool: *pg.Pool, random_number: u32) ![]const u8{
+        var conn = try pool.acquire();
+        defer conn.release();
+
+        const row_result = try conn.row("SELECT id, randomNumber FROM World WHERE id = $1", .{random_number});
+
         var row = row_result.?;
+        defer row.deinit() catch {};
 
         const world = World{ .id = row.get(i32, 0), .randomNumber = row.get(i32, 1) };
 
@@ -193,9 +201,7 @@ pub const DbEndpoint = struct {
             json_to_send = "null";
         }
 
-        req.sendBody(json_to_send) catch return;
-
-        return;
+        return json_to_send;
     }
 };
 

+ 25 - 5
frameworks/Zig/zap/src/main.zig

@@ -1,8 +1,8 @@
 const std = @import("std");
+const builtin = @import("builtin");
 const zap = @import("zap");
 const pg = @import("pg");
 const regex = @import("regex");
-const dns = @import("dns");
 const pool = @import("pool.zig");
 
 const endpoints = @import("endpoints.zig");
@@ -23,6 +23,24 @@ pub fn main() !void {
 
     const allocator = tsa.allocator();
 
+    var zap_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});
+
+        zap_port = arg_string; // use arg
+    }
+
+    var port = try std.fmt.parseInt(u16, zap_port, 0);
+
+    if (port == 0) {
+        port = 3000;
+    }
+
     var pg_pool = try pool.initPool(allocator);
     defer pg_pool.deinit();
 
@@ -68,7 +86,7 @@ pub fn main() !void {
     var listener = try zap.Middleware.Listener(middleware.Context).init(
         .{
             .on_request = null, // must be null
-            .port = 3000,
+            .port = port,
             .log = false,
             .max_clients = 100000,
         },
@@ -78,13 +96,15 @@ pub fn main() !void {
     );
     try listener.listen();
 
-    const cpuCount = @as(i16, @intCast(std.Thread.getCpuCount() catch 1));
+    //const cpuCount = @as(i16, @intCast(std.Thread.getCpuCount() catch 1));
+    //const workers = if (builtin.mode == .Debug) 1 else cpuCount;
+    const threads = 128;
 
-    std.debug.print("Listening on 0.0.0.0:3000 on {d} threads\n", .{cpuCount});
+    std.debug.print("Listening at 0.0.0.0:{d} on {d} threads\n", .{port, threads});
 
     // start worker threads
     zap.start(.{
-        .threads = 16 * cpuCount,
+        .threads = threads,
         .workers = 1,
     });
 }

+ 2 - 2
frameworks/Zig/zap/src/pool.zig

@@ -10,7 +10,7 @@ const Regex = regex.Regex;
 
 pub fn initPool(allocator: Allocator) !*pg.Pool {
     const info = try parsePostgresConnStr(allocator);
-    std.debug.print("Connection: {s}:{s}@{s}:{d}/{s}\n", .{ info.username, info.password, info.hostname, info.port, info.database });
+    //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,
@@ -60,7 +60,7 @@ fn addressAsString(address: std.net.Address) ![]const u8 {
 
 fn parsePostgresConnStr(allocator: Allocator) !ConnectionInfo {
     const pg_port = try getEnvVar(allocator, "PG_PORT", "5432");
-    std.debug.print("tfb port {s}\n", .{pg_port});
+    // std.debug.print("tfb port {s}\n", .{pg_port});
     var port = try std.fmt.parseInt(u16, pg_port, 0);
 
     if (port == 0) {

+ 10 - 0
frameworks/Zig/zap/start-servers.sh

@@ -0,0 +1,10 @@
+#!/bin/bash
+
+CPU_COUNT=$(nproc)
+P=3000
+END=$(($P+$CPU_COUNT))
+
+while [ $P -lt $END ]; do
+  zap $P &
+  let P=P+1
+done

+ 12 - 28
frameworks/Zig/zap/zap.dockerfile

@@ -9,38 +9,22 @@ ENV PG_HOST=tfb-database
 ENV PG_PORT=5432
 
 COPY src src
-COPY run.sh run.sh
-
 COPY build.zig.zon build.zig.zon
 COPY build.zig build.zig
+COPY start-servers.sh start-servers.sh
+COPY build-nginx-conf.sh build-nginx-conf.sh
+COPY nginx.conf nginx.conf
 
-RUN dnf install -y zig
-RUN zig version
-# RUN zig build -Doptimize=ReleaseFast 
-RUN zig build
-RUN cp /zap/zig-out/bin/zap /usr/local/bin
-
-EXPOSE 3000
-
-CMD ["sh", "run.sh"]
-
-# FROM alpine:3.19
+RUN chmod +x start-servers.sh
+RUN chmod +x build-nginx-conf.sh
 
-# WORKDIR /zap
+RUN ./build-nginx-conf.sh
 
-# ENV PG_USER=benchmarkdbuser
-# ENV PG_PASS=benchmarkdbpass
-# ENV PG_DB=hello_world
-# ENV PG_HOST=tfb-database
-# ENV PG_PORT=5432
-
-# RUN apk update
-# RUN apk add libc6-compat
-
-# COPY run.sh run.sh
-
-# COPY --from=build /zap/zig-out/bin/zap /usr/local/bin
+RUN dnf install -y zig nginx
+RUN zig version
+RUN zig build -Doptimize=ReleaseFast 
+RUN cp /zap/zig-out/bin/zap /usr/local/bin
 
-# EXPOSE 3000
+EXPOSE 8080
 
-# CMD ["sh", "run.sh"]
+CMD ./start-servers.sh && nginx -c /zap/nginx.conf -g "daemon off;"