diff --git a/config.nims b/config.nims index dca6b0d2..4e27fce5 100644 --- a/config.nims +++ b/config.nims @@ -1,6 +1,6 @@ import os putEnv("DB_SQLITE", $true) -# putEnv("DB_POSTGRES", $true) +putEnv("DB_POSTGRES", $true) # putEnv("DB_MYSQL", $true) # putEnv("DB_MARIADB", $true) diff --git a/example/benchmark.nim b/example/benchmark.nim index 9ebfb8f8..c5024c0b 100644 --- a/example/benchmark.nim +++ b/example/benchmark.nim @@ -1,4 +1,5 @@ import std/asyncdispatch +import std/db_postgres import std/json import std/random import std/os @@ -13,6 +14,7 @@ import ../src/allographer/query_builder randomize() let rdb = dbOpen(PostgreSQL, "allographer", "user", "Password!", "postgres", 5432, 95, 30, shouldDisplayLog=false) +let stdRdb = open("postgres:5432", "user", "Password!", "allographer") const range1_10000 = 1..10000 proc migrate() {.async.} = @@ -55,6 +57,9 @@ proc migrate() {.async.} = echo "=== finish migration" +let getFirstPrepare = stdRdb.prepare("getFirst", sql""" SELECT * FROM "World" WHERE id = $1 LIMIT 1 """, 1) +let updatePrepare = stdRdb.prepare("updatePrepare", sql""" UPDATE "World" SET "randomNumber" = $1 WHERE id = $2 """, 2) + proc query():Future[seq[JsonNode]] {.async.} = const countNum = 500 var futures = newSeq[Future[seq[string]]](countNum) @@ -64,70 +69,119 @@ proc query():Future[seq[JsonNode]] {.async.} = let resp = all(futures).await let response = resp.map( proc(x:seq[string]):JsonNode = - if x.len > 0: %*{"id": x[0].parseInt, "randomnumber": x[1]} + if x.len > 0: %*{"id": x[0].parseInt, "randomNumber": x[1].parseInt} + else: newJObject() + ) + return response + + +proc queryRaw():Future[seq[JsonNode]] {.async.} = + const countNum = 500 + var futures = newSeq[Future[seq[string]]](countNum) + for i in 1..countNum: + let n = rand(range1_10000) + futures[i-1] = rdb.raw(""" SELECT * from "World" WHERE id = ? LIMIT 1 """, $n).firstPlain() + let resp = all(futures).await + let response = resp.map( + proc(x:seq[string]):JsonNode = + if x.len > 0: %*{"id": x[0].parseInt, "randomNumber": x[1].parseInt} else: newJObject() ) return response +proc queryStd():Future[seq[JsonNode]] {.async.} = + const countNum = 500 + var resp:seq[Row] + for i in 1..countNum: + resp.add(stdRdb.getRow(getFirstPrepare, i)) + let response = resp.map( + proc(x:seq[string]):JsonNode = + %*{"id": x[0].parseInt, "randomNumber": x[1]} + ) + return response + + proc update():Future[seq[JsonNode]] {.async.} = const countNum = 500 var response = newSeq[JsonNode](countNum) - var updateFutures = newSeq[Future[void]](countNum) + var futures = newSeq[Future[void]](countNum) for i in 1..countNum: let index = rand(range1_10000) let number = rand(range1_10000) - updateFutures[i-1] = ( - proc() {.async.} = - discard rdb.table("World").select("id", "randomNumber").findPlain(index) - discard rdb.table("World").where("id", "=", index).update(%*{"randomNumber": number}) - response[i-1] = %*{"id":index, "randomNumber": number} + futures[i-1] = (proc():Future[void] = + discard rdb.table("World").select("id", "randomNumber").findPlain(index) + rdb.table("World").where("id", "=", index).update(%*{"randomNumber": number}) )() response[i-1] = %*{"id":index, "randomNumber": number} - await all(updateFutures) + await all(futures) return response -proc main() {.async.} = - migrate().waitFor - var queryResult = "" - var queryTime = 0.0 - var updateResult = "" - var updateTime = 0.0 +proc updateRaw():Future[seq[JsonNode]] {.async.} = + const countNum = 500 + var response = newSeq[JsonNode](countNum) + 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] = + discard rdb.raw(""" SELECT FROM "World" WHERE id = ? LIMIT 1 """, $index).firstPlain() + rdb.raw(""" UPDATE "World" SET "randomNumber" = ? WHERE id = ? """, $number, $index).exec() + )() + response[i-1] = %*{"id":index, "randomNumber": number} + await all(futures) + return response + + +proc updateRawStd():Future[seq[JsonNode]] {.async.} = + const countNum = 500 + var response = newSeq[JsonNode](countNum) + 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] = + discard stdRdb.getRow(getFirstPrepare, $index) + rdb.raw(""" UPDATE "World" SET "randomNumber" = ? WHERE id = ? """, $number, $index).exec() + )() + response[i-1] = %*{"id":index, "randomNumber": number} + await all(futures) + return response + + +proc timeProcess[T](name:string, cb:proc():Future[T]) {.async.}= + var start = 0.0 + var eachTime = 0.0 + var sumTime = 0.0 + var resultStr = "" for i in 1..5: - # ===== qeury - sleep(500) - var start = cpuTime() - for _ in 1..20: - discard query().await - var time = cpuTime() - start - queryTime += time - if i > 1: queryResult.add("\c\L") - queryResult.add(&"|{i}|{time}|") - - # ===== update sleep(500) start = cpuTime() for _ in 1..20: - discard update().await - time = cpuTime() - start - updateTime += time - if i > 1: updateResult.add("\c\L") - updateResult.add(&"|{i}|{time}|") - - - echo "query" + discard cb().await + eachTime = cpuTime() - start + sumTime += eachTime + if i > 1: resultStr.add("\n") + resultStr.add(&"|{i}|{eachTime}|") + + echo name echo "|num|time|" echo "|---|---|" - echo queryResult - echo fmt"|Avg|{queryTime / 5}|" + echo resultStr + echo fmt"|Avg|{sumTime / 5}|" echo "" - echo "update" - echo "|num|time|" - echo "|---|---|" - echo updateResult - echo fmt"|Avg|{updateTime / 5}|" + +proc main() = + migrate().waitFor + + timeProcess("query", query).waitFor + timeProcess("queryRaw", queryRaw).waitFor + timeProcess("queryStd", queryStd).waitFor + timeProcess("update", update).waitFor + timeProcess("updateRaw", updateRaw).waitFor + timeProcess("updateRawStd", updateRawStd).waitFor -main().waitFor \ No newline at end of file +main()