Comment by maccard

18 hours ago

> I would expect, actually, that it would be faster (all available cores get used).

And I think this assumption is what's killing us. Async != parallel for a start, and parallel IO is not guaranteed to be fast.

If you write a function:

    async Task<ImageFile> LoadFile(string path)
    {
        var f = await load_file(path);
        return new ImageFile(f);
    }

And someone comes along and makes it into a batch operation;

    async Task<List<ImageFile>> LoadFiles(List<string> paths)
    {
        var results = new List<ImageFile>();
        foreach(var path in paths) {
            var f = await load_file(path);
            results.Add(ImageFile(f));
        }
        return results;
    }

and provides it with 2 files instead of 1, you won't notice it. Over time 2 becomes 10, and 10 becomes 500. You're now at the mercy of whatever is running your tasks. If you yield alongside await [0] in an event loop, you introduce a loop iteration of latency in proceeding, meaning you've now introduced 500 loops of latency.

In case you say "but that's bad code", well yes, it is. But it's also very common. When I was reading for this reply, I found this stackoverflow [0] post that has exactly this problem.

[0] https://stackoverflow.com/questions/5061761/is-it-possible-t...

Why would someone put an await inside a loop?

Don't get me wrong... I believe you have seen it, I just can't understand the thought process that led to that.

In my mind, await is used when you want to use the result, not when you store it or return it.

  • The same can be asked about any number of things - why would someone ever not free their memory, use a dynamic allocation, not use a lock, use an orm, not use an orm.

    > I just can’t understand the thought process that led to that.

    Bluntly, it’s not understanding the tools and fundamentals. Your original reply assumed that it would use all cores, for example. To me that’s obviously not true but I’m sure there’s 10 things you could list off that are obvious to you but I’d get wrong -

    • > Your original reply assumed that it would use all cores, for example.

      Sure. My original reply assumed that there wouldn't be an unnecessary `await` inserted inside a loop.

      Unless I'm misunderstanding the code you posted, removing the `await` in the loop would use all cores.

well I mean you'd use await foreach and IAsyncEnumerable equivalent... async would mean the UI would not be blocked so I agree with the original commenter you replied to.

  • paraphrasing another reply I left here, if everyone just wrote their code correctly we’d all be writing C and everything would be safe and fast. I’ve fixed this exact issue with this exact cause (someone wrapped an await in a loop and it passed code review because our benchmark test still passed. But the benchmark test simulated the entire stack on a local network and when we deployed it, all of a sudden it took 5 seconds to load)