Linus Torvalds, who leads Linux kernel development, has published eight patches that improve file-read performance with the help of the AI coding assistant Claude Code. According to his October 10 description, a test in which eight threads repeatedly read the same file saw the number of operations per second rise roughly threefold. The improvement targets contention that occurs when multiple CPUs try to update a reference count while reading data cached in memory. However, what has been published is a prototype on a development branch, and the mechanism, which speeds up reads at the cost of delaying memory reuse, still has unresolved problems.
The biggest gains come when many threads read the same file
The benchmark Torvalds published in his October 10 explanatory commit was run on a laptop with a Core i7-8565U. The CPU has four cores and eight threads, with all cores sharing the L3 cache. The file system was ext4. In the test, each thread used its own file descriptor and repeatedly read 16 bytes from the start of the same file with pread(). The target file was one page in size.
The baseline was Linux 7.3-rc6 with modifications. CPU vulnerability mitigations and CONFIG_HARDENED_USERCOPY, which adds checks when copying data to user space, were disabled. In other words, this is not a result measured on a typical Linux distribution as shipped. Because the CPU frequency of the test PC varies with temperature, Torvalds also cautioned readers to look at the number of in-kernel CPU cycles per read rather than operations per second.
| 16-byte read condition | Cycles per read before | Cycles per read after |
|---|---|---|
| 1 thread | 452–454 | 408–409 |
| 8 threads reading the same file | 2,937–2,975 | 725–726 |
| 8 threads each reading a different file | 827 | 730–732 |
When eight threads read the same file, the number of in-kernel CPU cycles per read fell by about 75.3–75.6%. With one thread, the reduction was only about 9.5–10.1%.
These reduction rates were calculated from the measurements Torvalds published, using (1 − after ÷ before) × 100. For eight threads, the lower bound is (1 − 726 ÷ 2937) × 100 and the upper bound is (1 − 725 ÷ 2975) × 100, rounded to one decimal place. The single-thread figures were calculated in the same way by combining the two ends of the measured ranges, and they do not represent statistical confidence intervals.
In the test with eight threads reading the same file, operations per second also rose from about 10 million to the 30-million range. When each thread reads a different file, however, the difference in CPU cycles is much smaller.
In other words, the change is especially effective when multiple CPUs compete to update the management information for the same data. It does not mean that storage transfer speeds or overall Linux performance improve threefold across the board.
Why does simply reading data cause contention between CPUs?
File contents are not fetched from storage such as an SSD on every read. Linux keeps data it has read once in memory as the "page cache" and uses it for subsequent reads. One of the units used to manage this memory is the folio, which can handle multiple pages together.
In the conventional read path, to prevent a folio from being freed while data is being copied, the reference count is incremented before the read and decremented after the copy finishes. Even if the file contents are not modified, every read results in two writes to management information.
When multiple CPUs read the same folio, each must update the reference count safely. That requires passing the cache line containing the reference count back and forth between CPUs. When the amount of data being read is small, the waiting time caused by updating shared management information can be a bigger burden than the actual copying.
According to Torvalds, this problem was raised in 2024 by Matthew Wilcox, prompted by a customer workload.
In the eight-thread same-file test, the number of instructions executed in the kernel per read dropped from 988–989 to 864. CPU cycles, by contrast, fell to roughly a quarter. The large performance gain appears to come not just from executing fewer instructions, but from reducing the load of updating management information shared between CPUs.
Delaying memory reuse with RCU to avoid reference-count updates
The prototype takes the approach of not immediately reusing memory removed from the page cache for another purpose, and instead delaying reuse until reads can safely complete. This allows the fast read path to copy data directly into the user-space buffer without incrementing the folio's reference count.
The mechanism behind this is a synchronization mechanism called RCU (Read-Copy-Update). As explained in the official Linux documentation on RCU, RCU separates the removal of an item from a data structure from the actual freeing of its memory. Memory reuse waits until readers that were already referencing the item before its removal have finished their RCU read-side critical sections.
Importantly, it does not wait indefinitely for every newly started operation to finish. It secures a grace period long enough for existing readers to complete safely.
What this approach guarantees is not that a reference count is always held, but that memory being read is not reused for something else.
Methods for reading without incrementing the reference count had been considered before. That proposal tried to copy data into a temporary buffer and then verify that the retrieved content was correct. But it was difficult to handle situations in which memory is freed, used for something else, and then allocated again at the same location. The new design tries to avoid this problem by delaying the reuse of memory itself.
The patch that changes the actual read path also sets detailed conditions for using the fast path. Data is handled page by page so that the wrong page is not copied even if a folio is split. If the required data is not in the page cache, or if extra work such as readahead is needed, it switches to the conventional read path.
This is therefore not a change that eliminates Linux's reference-count management altogether.
Page faults are also disabled during the copy so that no waiting due to a page fault occurs inside the RCU read-side critical section. If the destination user memory is unavailable, the copy on the fast path is aborted, and the read switches to the conventional path to handle the page fault before continuing.
However, this switch comes at a performance cost.
In the October 10 measurements, for a 16-byte read where the destination user page is unavailable and a page fault must be handled, the cycles per thread rose from 4,117–4,188 to 6,543–6,593.
That means that even when the data is in the page cache, reads can be slower than before depending on the state of the destination memory. Evaluating the improvement requires taking into account the conditions under which the fast path can be used.
Waiting-to-be-freed memory becomes a new problem, and CMA regresses
In tests with only the first six patches applied, a problem occurred in which processes were forcibly terminated because of memory exhaustion.
This was observed in a virtual machine with 2 GiB of memory and swap disabled, when a workload that repeatedly allocated and freed file space ran at the same time as one that accessed a large anonymous memory region.
Even though memory awaiting reuse existed, the kernel could not properly gauge how much memory was available, and the OOM killer, detecting memory shortage, terminated processes.
To address this, the later patches add a mechanism that, when the amount of memory pending release accumulated per CPU grows, encourages the RCU grace period to end sooner and allocates CPU time to the freeing work.
In a test in which four processes each repeatedly allocated and freed 64 MiB of file space, the amount of memory waiting to be freed fell from an average of 565 MiB to 15 MiB. With all eight patches applied, the test that had reproduced the problem in the virtual machine above also ran to completion without stopping partway.
However, not all memory-management problems have been resolved.
Among the known issues Torvalds listed, pages awaiting release are still not reflected in counters that track free memory and similar figures. In a test with the load raised to 16 processes, even with all patches applied, an average of 177 MiB and a maximum of 870 MiB of memory sat waiting for reuse.
While contention in the read path is reduced, how to manage memory awaiting release and how much accumulation to tolerate have become new challenges.
In addition, a problem that did not occur before has been confirmed in CMA (Contiguous Memory Allocator), the mechanism for allocating physically contiguous memory regions.
In the current implementation, source pages remain in a pending-release state, so alloc_contig_range() can fail to allocate regions that were previously used by the page cache. Countermeasures such as waiting for memory release to complete before allocating had not been implemented at the time of the description.
Other items listed for further consideration include the effect of changing the page-ownership transfer in splice() to a copy-based approach, and conflicts with protected memory on the s390 architecture. The overall processing cost for workloads with frequent memory freeing has also not yet been measured.
While reads have become faster, it needs to be examined carefully whether the burden has simply shifted to other processing.
How much did Claude Code do, and will it reach mainline Linux?
In his description, Torvalds reveals that he used Claude Code not only to write code and test programs, but also for reviews to organize known issues and for a first draft of the description.
He says all of this was done under his own direction and that the performance measurements were run on his own machine. The patch that changes the read path carries Assisted-by: LLM, indicating AI assistance, along with Torvalds's own Signed-off-by.
However, the fact that AI assisted in writing the code and tests does not by itself mean that the independence of verification is ensured.
In this testing, reads were performed concurrently with processing that evicts data from the page cache and reuses the memory, and every byte retrieved was verified. Across about 100 million reads over 30 seconds, no data errors were detected.
On the other hand, in a control test using an early version with the delayed-free mechanism deliberately removed, reads of incorrect data were detected. Torvalds also states explicitly that this control test has not been rerun on the current version.
Many items remain unverified. The file-system test suite xfstests has not been run, nor has the situation in which a folio is split during a read been tried. Memory-error checking with KASAN, 32-bit environments, and verification on other machines have also not been carried out.
There is an outlook that servers with multiple CPU sockets could see even larger improvements, but there are no measured results at present.
The official Linux guidelines on tool-generated content require that the submitter understand the entire change and be able to answer questions during review. They also emphasize disclosing the tools used, their scope of influence, and the tests performed, and maintainers can request additional verification as needed.
In other words, even if AI use is properly disclosed, that alone does not mean a patch will be accepted.
The Linux mainline (master) log as checked on October 12 had advanced to Linux 7.3-rc7, but these eight patches are at the prototype stage, published on a dedicated development branch, and no date for formal adoption has been set.
Going forward, in addition to resolving the problem that arose with CMA, it will be necessary to measure the load of memory-release processing and to verify safety on different hardware configurations. If these challenges can be resolved, the approach could significantly reduce the waiting time caused by reference-count updates when many CPUs read the same file.
