<<exa queries files in parallel, giving you performance on par with ls.>>
I think that this is bullshit! Maybe the author thinks that it is really the case, probably tricked by the language, because using async, but in the end, the syscall to read folders is synchronous...
The syscall to list a directory is synchronous, but the follow-up stat calls to read file attributes (type, permission, attributes, size) are done one file at a time, so there are opportunities for parallelization.
Incidentally, this is why ls without colors or type symbols (-l, -F, --color, and so forth) is a lot faster: it doesn't have to query every file to find out what it is in order to display the color/symbol/permissions/etc. Handy if you're on a slow networked file system and just need to see names.
It would be better if it used fstatat instead of regular stat calls. On a deeply nested directory it can make a difference (e.g. a single-threaded 'find' easily beats a parallel 'fd' with warm caches on my machine, 'exa' could similarly benefit)
> but the follow-up stat calls to read file attributes (type, permission, attributes, size) are done one file at a time, so there are opportunities for parallelization.
You may expect so but this is usually not the case. Multiple threads submitting stat or other fs ioctl commands to the disk driver are going to be sequenced and may not be threaded.
This is definitely how it works on Windows. Linux is better, but a lot of disk IO is behind the times. io_uring only has read/write so far.
I don't see how parallelism could work with stat() in general, since the OS has to keep the FS structures consistent and ultimately there is only one disk to read from, unless you have RAID.
Filling the disk queue usually helps with the IO throughout part, sequential stats not attempting to queue requests will never saturate the bandwidth of a modern device.
There's also the page cache involved for reads, so it can be read while actual IO is queued.
It's not reading the folders that is the main slowdown in ls (and exa and similar) for more complex lists, but all the extra work done per file.
ls and similar can (and do) requests the files in batches, so if the directory has enough files for speed to matter you can request one and then asynchronously query whatever additional information you need.
If you only want the filename and whether it's a directory, device or file, then you won't do much better than ls, but you also likely won't do much worse.
But the moment you want e.g. filesize you need to stat() files. That too will be the same whether or not it's ls. But exa also does things like check git and that will add significant overhead that they may or may not alleviate by doing it in parallel.
I think that this is bullshit! Maybe the author thinks that it is really the case, probably tricked by the language, because using async, but in the end, the syscall to read folders is synchronous...