Optimised `await` on custom async procs.
* The async proc is now invoked immediately after the 'await' request is processed. This means that the iterator is executed until it yields with a request which cannot be immediately satisfied (e.g. readLine) after which point a select() call will need to be made. Previously the async proc would only be added to the list of requests, the event loop would need to start over and thus would need to go through each request again before invoking the iterator and reaching a request which could not be immediately satisfied. * This was implemented by recursively calling the processWorker procedure in asyncio.nim. In the future it may be of benefit to also perform this for reqReg. * When the awaited user-defined async proc finishes, the parent worker will be executed, the same optimisation has been used for that case. * The way that this optimisation is implemented means that even multiple levels of awaited user-defined procs will be quickly processed. (Look at the tasyncitermacro test, the auth procs are arranged this way to test this)
This commit is contained in:
parent
70d67daa14
commit
e42f877664
2 changed files with 21 additions and 11 deletions
|
|
@ -671,9 +671,7 @@ proc processWorkers(d: PDispatcher) =
|
|||
var newRequests: array[TRequestKind, seq[PWorker]] = d.requests
|
||||
newRequests[reqNil] = @[]
|
||||
|
||||
|
||||
|
||||
for idle in d.requests[reqNil]:
|
||||
proc processWorker(idle: PWorker) =
|
||||
let req = idle.worker(idle.x)
|
||||
if req != nil:
|
||||
echo("Process workers, after exec: ", req.kind)
|
||||
|
|
@ -684,13 +682,16 @@ proc processWorkers(d: PDispatcher) =
|
|||
x: req)
|
||||
newRequests[reqNil].add(newWorker)
|
||||
of reqAwait:
|
||||
# For efficiency lets execute this async proc now.
|
||||
let awaitReq = req.worker(req)
|
||||
let newWorker = PWorker(worker: req.worker, lastReq: awaitReq,
|
||||
let newWorker = PWorker(worker: req.worker, lastReq: PRequest(kind: reqNil),
|
||||
x: req, hasParent: true, parent: idle)
|
||||
# The worker which ``await``-ed this user-defined async proc;
|
||||
# will be re-added to ``d.requests`` when ``newWorker`` finishes.
|
||||
newRequests[awaitReq.kind].add(newWorker)
|
||||
|
||||
# We call this proc recursively so that the execution of this
|
||||
# worker begins and we can immediately satisfy it's async request.
|
||||
# We do not need to add newWorker to newRequests manually as it will be
|
||||
# added by ``processWorker`` if necessary automatically.
|
||||
processWorker(newWorker)
|
||||
else:
|
||||
idle.lastReq = req
|
||||
newRequests[req.kind].add(idle)
|
||||
|
|
@ -698,10 +699,14 @@ proc processWorkers(d: PDispatcher) =
|
|||
assert idle.worker.finished
|
||||
if idle.hasParent:
|
||||
# Re-add the parent worker, which is the worker which awaited this
|
||||
# user-defined async proc which just finished.
|
||||
newRequests[reqNil].add(idle.parent)
|
||||
# user-defined async proc which just finished. Do this by calling
|
||||
# processWorker recursively. Same way as above.
|
||||
processWorker(idle.parent)
|
||||
echo("Await finish: ", idle.parent.lastReq.kind)
|
||||
|
||||
for idle in d.requests[reqNil]:
|
||||
processWorker(idle)
|
||||
|
||||
d.requests = newRequests
|
||||
|
||||
template popu(req) {.immediate, dirty.} =
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
import sockets, asyncio, strutils
|
||||
|
||||
proc auth(client: PAsyncSocket) {.async.} =
|
||||
proc auth3(client: PAsyncSocket) {.async.} =
|
||||
await send(client, "Auth\c\L")
|
||||
|
||||
proc auth2(client: PAsyncSocket) {.async.} =
|
||||
await auth3(client)
|
||||
|
||||
proc auth(client: PAsyncSocket) {.async.} =
|
||||
await auth2(client)
|
||||
|
||||
proc processRequest(client: PAsyncSocket, test: string, closeSock: bool = true) {.async.} =
|
||||
assert test == "ahha"
|
||||
assert client != nil
|
||||
|
|
@ -11,7 +17,6 @@ proc processRequest(client: PAsyncSocket, test: string, closeSock: bool = true)
|
|||
|
||||
for i in 0 .. 10:
|
||||
await auth(client)
|
||||
#await send(client, "Auth\c\L")
|
||||
|
||||
await send(client, "Goodbye.\c\L")
|
||||
if closeSock:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue