From 381398a16a62193c2b0223e0993659fc9de7d5fd Mon Sep 17 00:00:00 2001 From: Dragos Varovici Date: Wed, 25 Sep 2024 15:33:26 -0600 Subject: [PATCH] Zap performance improvements --- frameworks/Zig/zap/build-nginx-conf.sh | 13 +++++++++ frameworks/Zig/zap/build.zig | 19 ------------ frameworks/Zig/zap/build.zig.zon | 1 - frameworks/Zig/zap/nginx.conf | 33 +++++++++++++++++++++ frameworks/Zig/zap/run.sh | 3 -- frameworks/Zig/zap/src/endpoints.zig | 24 ++++++++++------ frameworks/Zig/zap/src/main.zig | 30 +++++++++++++++---- frameworks/Zig/zap/src/pool.zig | 4 +-- frameworks/Zig/zap/start-servers.sh | 10 +++++++ frameworks/Zig/zap/zap.dockerfile | 40 ++++++++------------------ 10 files changed, 110 insertions(+), 67 deletions(-) create mode 100644 frameworks/Zig/zap/build-nginx-conf.sh create mode 100644 frameworks/Zig/zap/nginx.conf delete mode 100644 frameworks/Zig/zap/run.sh create mode 100644 frameworks/Zig/zap/start-servers.sh diff --git a/frameworks/Zig/zap/build-nginx-conf.sh b/frameworks/Zig/zap/build-nginx-conf.sh new file mode 100644 index 00000000000..ecb55c80bfa --- /dev/null +++ b/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 diff --git a/frameworks/Zig/zap/build.zig b/frameworks/Zig/zap/build.zig index 762284c2acb..2da55a07981 100644 --- a/frameworks/Zig/zap/build.zig +++ b/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); } diff --git a/frameworks/Zig/zap/build.zig.zon b/frameworks/Zig/zap/build.zig.zon index 871e73b7f76..3f492b7d954 100644 --- a/frameworks/Zig/zap/build.zig.zon +++ b/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" }, } } diff --git a/frameworks/Zig/zap/nginx.conf b/frameworks/Zig/zap/nginx.conf new file mode 100644 index 00000000000..f394b2ad206 --- /dev/null +++ b/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; + } + } +} diff --git a/frameworks/Zig/zap/run.sh b/frameworks/Zig/zap/run.sh deleted file mode 100644 index b4698a15de1..00000000000 --- a/frameworks/Zig/zap/run.sh +++ /dev/null @@ -1,3 +0,0 @@ -echo "Waiting for ZAP framework to start..." - -zap \ No newline at end of file diff --git a/frameworks/Zig/zap/src/endpoints.zig b/frameworks/Zig/zap/src/endpoints.zig index 3492e686591..44a3afc43e2 100644 --- a/frameworks/Zig/zap/src/endpoints.zig +++ b/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; } }; diff --git a/frameworks/Zig/zap/src/main.zig b/frameworks/Zig/zap/src/main.zig index 0c66a7639bb..e2792726f04 100644 --- a/frameworks/Zig/zap/src/main.zig +++ b/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, }); } diff --git a/frameworks/Zig/zap/src/pool.zig b/frameworks/Zig/zap/src/pool.zig index 84df32104b0..6615ae217ce 100644 --- a/frameworks/Zig/zap/src/pool.zig +++ b/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) { diff --git a/frameworks/Zig/zap/start-servers.sh b/frameworks/Zig/zap/start-servers.sh new file mode 100644 index 00000000000..b5cf175de41 --- /dev/null +++ b/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 diff --git a/frameworks/Zig/zap/zap.dockerfile b/frameworks/Zig/zap/zap.dockerfile index 9aa8a4109ae..71123f4f3e7 100644 --- a/frameworks/Zig/zap/zap.dockerfile +++ b/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"] \ No newline at end of file +CMD ./start-servers.sh && nginx -c /zap/nginx.conf -g "daemon off;" \ No newline at end of file