0

I have a process thats reading the whole filesystem and hashing files. It slows down (by 4x or so) because the reads are causing a lot of seeking. Small chunks of each file are being read by each of 4 threads but if I test a sequential read by copying (cp) I can read far faster. CPU utilisation is at 25% so its not cpu bound. I am fairly sure seeking is the problem.

I've read that the kernel has quite sophisticated disk reading strategies to speed up access so I wonder if kernel buffers are restricting their use here, and if they could be increased to allow it to buffer more. I assume the program I am using is only requesting a fairly small chunk of data with each read call so I don't know if this would be effective.

I imagine reading each file into memory fully one by one would be most effective but I can't rewrite the application at the moment (its not mine, and its large and bloated imo). But could I get the OS to read each file as it is opened into buffers entirely (or even partially, like 100 - 500MB at a time), sequentially, so that the application threads are only making a call to memory with each of their small reads rather than a call to disk (causing a seek)?

ADDED LATER:

@Artem cache does not seem to do the job here and I guess I can understand why. The kernel is trying to be 'sensible' and saying "I'm not going to read a whole 500MB file into memory, just because the user has requested the first MB". Which makes sense. What is loaded in will be cached indeed so if its used again (for example by another process) it can be fetched from memory. But what I want is the kernel to load the whole file in to cache on the first read (that first read being what, 2MB maybe?).

So the system call is read(fd, buf, size). If I'm programming C I would never put a huge buffer as size and I doubt many programmers would. So it was probably written using a more normal sort of buffer size, a meg or two.

So the user process gets a MB or two and enters the hashing function which keeps it busy for a while, and it stops pestering the kernel for a disk read. Meanwhile theres another disk read queued by a different thread for a read of a different part of the disk. So the kernel services that now, and the disk seeks to a different part of the disk taking ~15ms.

Whats a shame is that files are generally held in quite large extents of sequential blocks on disk. So a sustained read of the disk for that first file would probably have read hundreds of thousands, even a million blocks, tens or hundreds of MB, without any seeking. That there is high performance disk reading and its what I want to encourage.

But no the way things are working, the processes are requesting small chunks of data, the kernel is trying to be sensible and not read massive amounts of data that no one has even asked for (holding up waiting processes in by doing so), and as a result its seeking around like mad and spending all its time seeking.

Contrast this with 'cp -r' - only 1 thread is asking the kernel to read files. So theres no one telling the disk head to seek to a different part of the disk every MB or two, so when subsequent reads come in to the kernel the drive is in a position to get the data quickly.

The code could be rewritten with much larger buffers so thats one option for me. But as I say I was wondering if it was possible to instruct the kernel to buffer 'ahead' much more. Kind of like 'read ahead caching'. Predicting that files, once opened, are going to be read in their entirety, so filling read buffers with at least n bytes before stopping the physical disk read to kernel buffers for each file read.

4
  • Are your threads also writing to the same filesystem ? Commented Apr 7, 2024 at 10:16
  • It slows down by 4×, compared to what? Commented Apr 7, 2024 at 12:02
  • @MC68020 there is virtually no writing going on - the threads calculate MD5 and SHA256 and write that so each file only results in the writing of a couple of hundred bytes. The slowdown of 4x is based on the fact that the disk can read by cp at about 180 MBs, and a single thread can manage creation of the hashes at about 40 - 50 MBs. But I am only managing 15-25 MBs when setting it all to multithreading and trying to use all 4 cores in the CPU (it slows down slightly when I do that compared to 1 thread). Which I imagine is the fault of all that seeking. Commented Apr 8, 2024 at 8:57
  • @MC68020 sorry missed that question re same FS. No they are not writing to the same FS, they are writing to the SSD the system is installed on (home directory). The source disk is a 6TB magnetic disk (hence the slow seek time). Commented Apr 8, 2024 at 12:14

1 Answer 1

0

The Linux kernel uses your entire available RAM for filesystem caching. You cannot make it use more.

You could try using a higher values of swappiness but I'm 99% sure it won't help.

Probably you need more RAM.

1
  • Theres 16G ram on it at the moment and if that was used it would work fine I think - most of the files are well under 4GB ram. Maybe 90% of the space is used with files < 200 MB. I understand what you mean in your comment but that caching is not actually whats needed here. I expand on your comment in the answer because of space, thx. Commented Apr 8, 2024 at 9:05

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.