# nim c -r --threads:off -d:reset example/postgres/benchmark.nim import std/asyncdispatch import std/json import std/os import std/random import std/strutils import std/monotimes import std/times import ../../src/allographer/connection import ../../src/allographer/query_builder import ../../src/allographer/schema_builder randomize() const range1_10000 = 1..10000 countNum = 500 shouldDisplayLog = false pgUrl = "postgresql://user:pass@postgres:5432/database" selectSql = """SELECT "index" as id, "randomNumber" FROM "World" WHERE "index" = ?""" updateSql = """UPDATE "World" SET "randomNumber" = ? WHERE "index" = ?""" maxConnections = 95 timeout = 30 let rdb = dbOpen(PostgreSQL, pgUrl, maxConnections, timeout, shouldDisplayLog=shouldDisplayLog) proc timeProcess(name: string, cb: proc(): Future[void]) {.async.} = var eachTime = 0.0 var sumTime = 0.0 const repeatCount = 5 var resultStr = "" for i in 1..repeatCount: sleep(100) let start = getMonoTime() await cb() eachTime = float64((getMonoTime() - start).inMilliseconds) / 1000.0 sumTime += eachTime if i > 1: resultStr.add("\n") resultStr.add("|" & $i & "|" & $eachTime & "|") echo name echo "|num|time|" echo "|---|---|" echo resultStr echo "|Avg|" & $(sumTime / repeatCount) & "|" echo "" rdb.create( table("World", [ Column.increments("index"), Column.integer("randomNumber").default(0) ]) ) seeder(rdb, "World"): var data = newSeq[JsonNode]() for i in range1_10000: data.add( %*{"randomNumber": rand(range1_10000)} ) rdb.table("World").insert(data).waitFor proc benchUpdate() {.async.} = var futures = newSeq[Future[void]](countNum) for i in 1..countNum: let index = rand(range1_10000) let number = rand(range1_10000) futures[i - 1] = (proc(): Future[void] {.async.} = discard rdb.select("index as id", "randomNumber").table("World").where("index", "=", index).first().await rdb.table("World").where("index", "=", index).update(%*{"randomNumber": number}).await )() await all(futures) proc benchUpdatePreparedCold() {.async.} = let selectStmt = rdb.prepare(selectSql) let updateStmt = rdb.prepare(updateSql) defer: selectStmt.close().await updateStmt.close().await var futures = newSeq[Future[void]](countNum) for i in 1..countNum: let index = rand(range1_10000) let number = rand(range1_10000) futures[i - 1] = (proc(): Future[void] {.async.} = rdb.withConn( proc(ctx: PostgresPreparedContext): Future[void] {.async.} = discard await selectStmt.first(ctx, @[$index]) await updateStmt.exec(ctx, @[$number, $index]) ) )() await all(futures) let selectStmtWarm = rdb.prepare(selectSql) let updateStmtWarm = rdb.prepare(updateSql) proc benchUpdatePreparedWarm() {.async.} = var futures = newSeq[Future[void]](countNum) for i in 1..countNum: let index = rand(range1_10000) let number = rand(range1_10000) futures[i - 1] = (proc(): Future[void] {.async.} = rdb.withConn( proc(ctx: PostgresPreparedContext): Future[void] {.async.} = discard await selectStmtWarm.first(ctx, @[$index]) await updateStmtWarm.exec(ctx, @[$number, $index]) ) )() await all(futures) proc main(){.async.} = await timeProcess("postgres benchmark", benchUpdate) await timeProcess("postgres benchmark prepared cold", benchUpdatePreparedCold) await timeProcess("postgres benchmark prepared warm", benchUpdatePreparedWarm) main().waitFor