I don't want to file an issue, because maybe the problem is in my code. Below is the minimal test (also available as gist).
So, the problem is that if I use deprecated API from httpclient, I get maximum performance while producing http request.
TEST[SyncClient]: Processed 1000 requests in 40 seconds!
TEST[DeprecatedAPI]: Processed 1000 requests in 1 seconds!
TEST[ApacheBenchmark]: Processed 1000 requests in 1 seconds!
And sometimes test that uses deprecated API fails with error:
Traceback (most recent call last)
test.nim(64) test
test.nim(59) main
test.nim(37) runSyncTest
httpclient.nim(646) postContent
httpclient.nim(618) post
httpclient.nim(529) request
httpclient.nim(482) request
net.nim(1507) connect
os.nim(154) raiseOSError
Error: unhandled exception: Connection refused [OSError]
Why postContent is so slow when using HttpClient? When I replace postContent on get, both tests works with the same speed, 1 second.
import asynchttpserver,
httpclient,
asyncdispatch,
net,
os,
osproc,
times
type
TestType = enum SyncClient, DeprecatedAPI, ApacheBenchmark
const port = Port(8888)
const testType = SyncClient
const requestsTotal = 1000
const postBody = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
proc serverThread {.thread.} =
var server = newAsyncHttpServer()
proc cb(req: Request) {.async.} =
await respond(req, Http200, "OK")
waitFor serve(server, port, cb)
proc runSyncTest(requests: int) =
when testType == SyncClient:
let c = newHttpClient()
when testType != ApacheBenchmark:
for _ in 1..requests:
when testType == SyncClient:
discard c.postContent("http://localhost:" & $port, postBody)
else:
discard postContent("http://localhost:" & $port, postBody)
when testType == SyncClient:
c.close
else:
let file = getTempDir() / "httpclient.test"
defer:
removeFile file
writeFile file, postBody
let cmd = "ab -n " & $requests & " -p " & file & " http://localhost:" & $port & "/"
echo "AB command: ", cmd
discard execCmd(cmd)
proc main() =
var server: Thread[void]
createThread(server, serverThread)
let t = getTime()
runSyncTest(requestsTotal)
echo "TEST[", testType, "]: Processed ", requestsTotal, " requests in ", getTime() - t, " seconds!"
when isMainModule:
main()
I ran your code and I got consistent result with SyncClient faster than DeprecatedApi.
I've ran it in Windows 10 (gcc-mingw64, withouth ab), and Linux subsystem, all results are consistent.
TEST[SyncClient]: Processed 1000 requests in 43 seconds!
TEST[DeprecatedAPI]: Processed 1000 requests in 0 seconds!
TEST[ApacheBenchmark]: Processed 1000 requests in 0 seconds!
Same results here..Sync is very slow
on win7 64 and Nim Compiler Version 0.16.1 (2017-02-09) [Windows: amd64]
TEST[SyncClient]: Processed 1000 requests in 1 seconds!
or 0 seconds
Interesting. I got the results above on Ububtu 16.04. Rechecked on Windows 8. The problem is that SyncClient test is so slow only on linux! And it's faster then DeprecatedAPI on windows.
Debugging shows that it hangs for some time here: https://github.com/nim-lang/Nim/blob/devel/lib/pure/httpclient.nim#L829