1

Currently I'm using async for _ in asyncgen(): pass

I'm looking for "fast route" implementation, approach for sync generators would be:

deque(maxlen=0).extend(generator)
Slam
  • 8,112
  • 1
  • 36
  • 44
  • After a quick benchmark, `deque(maxlen=0).extend(gen)` seems to be about 20% faster than `for _ in gen: pass`. The C optimization of the deque approach doesn't seem to be the bottleneck here :) – Vincent Apr 05 '19 at 16:10
  • I don't understand. I know that deque drains generators faster than anything else. I'm looking to do the same for _async_ generator, deque can't consume it, afaik – Slam Apr 05 '19 at 16:22
  • 1
    What I meant is that a 20% speedup is not what one would expect by switching to a C-based approach (I usually expect something like a 10 times factor improvement). That's because the bottleneck is somewhere else: the slow part is not the draining of the generator but the execution of the python code within that generator. My advice would be to simply not bother and use `for _ in gen: pass` or `async for _ in agen`. – Vincent Apr 05 '19 at 16:46
  • 1
    Note that the deque is not consistently faster; a simple `for` loop is more efficient with small sequences. (On my machine the cut-off point is somewhere around 16 elements.) – user4815162342 Apr 05 '19 at 22:53

1 Answers1

5

Not an answer to your question:

When it comes to plain generators, deque seems to be just slightly faster than for-loop (over 10%). One can argue that using deque won't bring any practical advantage and doesn't worth its unreliability and possible side effects.

But it becomes much more important when we talk about asynchronous programming. Word async tells us that there's some I/O happens inside this async generator: otherwise there was no reason to make this generator asynchronous in the first place. This I/O probably takes over 99% of execution time (see this answer and especially last code snippet there). It'll transform 10% of fast iterating advantage to something completely miserable.

We just won't see any measurable difference between async for loop and alternative approach after all efforts put into optimization.

Generally speaking, "premature optimization is the root of all evil" and only "3% of critical code" is worth optimizing. Which 3% can only be said after measurements and when it comes to asynchronous programming it'll probably be I/O stuff, not iterating.


An answer to your question:

deque works faster than for loop only because it's implemented in C. There's no (known to me) C implementation of similar functions that work with async iterables. Thus I'm afraid async for _ in asyncgen(): pass is only option you have right now if you don't want to write C code.

Mikhail Gerasimov
  • 36,989
  • 16
  • 116
  • 159