I'd like to make the
ls -laR /media/myfs on Linux as fast as possible. I'll have 1 million files on the filesystem, 2TB of total file size, and some directories containing as much as 10000 files. Which filesystem should I use and how should I configure it?
As far as I understand, the reason why
ls -laR is slow because it has to
stat(2) each inode (i.e. 1 million
stat(2)s), and since inodes are distributed randomly on the disk, each
stat(2) needs one disk seek.
Here are some solutions I had in mind, none of which I am satisfied with:
Create the filesystem on an SSD, because the seek operations on SSDs are fast. This wouldn't work, because a 2TB SSD doesn't exist, or it's prohibitively expensive.
Create a filesystem which spans on two block devices: an SSD and a disk; the disk contains file data, and the SSD contains all the metadata (including directory entries, inodes and POSIX extended attributes). Is there a filesystem which supports this? Would it survive a system crash (power outage)?
find /media/myfson ext2, ext3 or ext4, instead of
ls -laR /media/myfs, because the former can the advantage of the
d_typefield (see in the
getdents(2)man page), so it doesn't have to stat. Unfortunately, this doesn't meet my requirements, because I need all file sizes as well, which
find /media/myfsdoesn't print.
Use a filesystem, such as VFAT, which stores inodes in the directory entries. I'd love this one, but VFAT is not reliable and flexible enough for me, and I don't know of any other filesystem which does that. Do you? Of course, storing inodes in the directory entries wouldn't work for files with a link count more than 1, but that's not a problem since I have only a few dozen such files in my use case.
Adjust some settings in
sysctlso that inodes are locked to system memory forever. This would not speed up the first
ls -laR /media/myfs, but it would make all subsequent invocations amazingly fast. How can I do this? I don't like this idea, because it doesn't speed up the first invocation, which currently takes 30 minutes. Also I'd like to lock the POSIX extended attributes in memory as well. What do I have to do for that?
Use a filesystem which has an online defragmentation tool, which can be instructed to relocate inodes to the the beginning of the block device. Once the relocation is done, I can run
dd if=/dev/sdb of=/dev/null bs=1M count=256to get the beginning of the block device fetched to the kernel in-memory cache without seeking, and then the
stat(2)operations would be fast, because they read from the cache. Is there a way to lock those inodes and/or blocks into memory once they have been read? Which filesystem has such a defragmentation tool?