Presumably, with async you could queue all the `stat`-ops after the dir walk at once, leaving the total latency in the ball park of "dir walk"+"ping for file stat"+"ping remaining symlink stats if present". But I don't think `ls` does this.
Otherwise, yeah, you incur network latency on every file, plus, as you say, symlink "pings" if those are present. So its "dir walk"+"number of files"*"ping"+"symlinks"*"ping", which adds up.
Batching high-latency ops is one of the only cases where I like async.
NFS version 3 already has the READDIRPLUS operation which returns the directory contents and all of the stats together in one call to improve performance for this case. Sometimes the kernel client doesn't use READDIRPLUS and falls back to issuing a bunch of requests - usually because it's being super conservative about security (as if there is such a thing in NFS). It's also not that straightforward for a utility like ls to tell the kernel that it's reading both the directory and the stats for each file - they're separate system calls and the kernel has to figure out what the program is trying to do and optimise.
I wrote a tool that issues raw READDIRPLUS requests to list a directory:
Wow, thanks! I’m definitely going to try this tool. I have use cases at work where I need to look at files in an NFS server on the other side of the country from my home desktop (don’t ask… it’s much bigger PITA to get SSH access to a VM near the NFS server than it should be) and it takes ages to run ls in a directory.
Otherwise, yeah, you incur network latency on every file, plus, as you say, symlink "pings" if those are present. So its "dir walk"+"number of files"*"ping"+"symlinks"*"ping", which adds up.
Batching high-latency ops is one of the only cases where I like async.