karlseguin / pg.zig

Native PostgreSQL driver / client for Zig
MIT License
214 stars 16 forks source link

Benchmarks against other clients/drivers #8

Open kitsuniru opened 8 months ago

kitsuniru commented 8 months ago

Interesting, how it will act against tokio_postgres or pgx

karlseguin commented 8 months ago

I think it's hard to do because there are many use cases, and different use cases might have different hotspots. If you're doing a large insert, binding performance might be the concern. If you're reading a lot of data, parsing and network might be. If we're reading, should we clone the results and own the bytes, or not?

Also, the query execution (within postgresql) and network transfer (even over localhost) often accounts for the majority of the time any query takes. It's hard to measure something when it's only a small percentage of the overall cost.

For what it's worth, the following takes roughly the same time:

package main

import (
    "context"
    "fmt"
    "time"

    "github.com/jackc/pgx/v5"
)

func main() {
    conn, err := pgx.Connect(context.Background(), "postgres://localhost:5432/postgres")
    if err != nil {
        panic(err)
    }
    defer conn.Close(context.Background())

    start := time.Now()
    for i := 0; i < 100; i += 1 {
        rows, err := conn.Query(context.Background(), "select generate_series(1,100000) as id, md5(random()::text)")
        if err != nil {
            panic(err)
        }

        sum := 0
        l := 0
        for rows.Next() {
            var id int
            var hash string
            if err := rows.Scan(&id, &hash); err != nil {
                panic(err)
            }
            sum += id
            l += len(hash)
        }
        rows.Close()
        if sum != 5000050000 || l != 3200000 {
            panic("fail")
        }
    }
    fmt.Println(time.Now().Sub(start))
}
const std = @import("std");
const pg = @import("pg");
const Allocator = std.mem.Allocator;

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    var conn = try pg.Conn.open(allocator, .{});
    try conn.auth(.{});

    const start = std.time.milliTimestamp();
    for (0..100) |_| {
        var result = try conn.query("select generate_series(1,100000) as id, md5(random()::text)", .{});
        defer result.deinit();

        var sum: usize = 0;
        var l: usize = 0;
        while (try result.next()) |row| {
            const id = row.get(i32, 0);
            const hash = row.get([]u8, 1);

            sum += @intCast(id);
            l += hash.len;
        }
        if (sum != 5000050000 or l != 3200000) {
            @panic("fail");
        }
    }
    std.debug.print("{d}\n", .{std.time.milliTimestamp() - start});
}