Re: [linux-next:master] [mm] 7b32f64bc5: pts.svt-av1.Preset13.Bosphorus4K.frames_per_second 45.8% regression
Pedro Falcato <[email protected]> Tue, 28 Jul 2026 11:33:22 +0100
| Newsgroups | dev.linux.lists.oe-lkp,org.kernel.vger.linux-fsdevel,org.kvack.linux-mm |
|---|---|
| Message-ID | <[email protected]> |
On Mon, Jul 27, 2026 at 09:46:10AM +0800, Bo Zhang wrote: > On Thu, Jul 23, 2026 at 01:34:38PM -0700, Frederick Mayle wrote: > > I maybe missing something subtle, but, I think you've changed it from "don't > > read beyond the VMA" to "if there is a chance we could read beyond the VMA, > > don't read beyond the VMA", which seems like a more complex expression of the > > same behavior. > > Hi Frederick, > > The subtlety is in how async readahead interacts with _max_index. The two > are not equivalent because async readahead sets ra->start to the end of > the previous readahead window, not to vmf->pgoff. So even though the user > is still faulting well inside the VMA, the readahead target (ra->start) > has already moved past the VMA end, however _max_index blocks it. > > Here is the concrete scenario (ra_pages=128, VMA covers pages 0-1023): > > 1. Fault at page 0 triggers sync readahead: reads pages 0-127, > places PG_readahead marker at page ~96. > > 2. Sequential faults continue. Fault at page 96 hits PG_readahead, > triggers async readahead in do_async_mmap_readahead(). > > 3. page_cache_async_ra() detects sequential pattern (index == expected) > and does: > ra->start += ra->size; /* pushes start to end of previous window */ > So ra->start = 128 (NOT vmf->pgoff=96), ra->size = 256 which is doubled > > 4. page_cache_ra_order() calculates: > limit = min(file_end, ractl->_max_index) > > With the unconditional approach: > _max_index = 1023 (always set) > limit = 1023, ra->start(128) < limit (It works fine here) > > But after several ramp-ups, when the window reaches the boundary: > > 5. Fault at page ~896 hits PG_readahead, async readahead fires. > page_cache_async_ra() does ra->start += ra->size: > ra->start = 1024 (previous window ended at 1023) > ra->size = 128 > > 6. page_cache_ra_order(): > limit = min(file_end, 1023) = 1023 > ra->start(1024) > limit(1023) (Which will read NOTHING) > > Result: page 1024 (in VMA2) is never prefetched. When the process > enters VMA2, it takes a major fault and readahead ramps up from scratch. That's on purpose. > > With my conditional approach: > At step 5, vmf->pgoff=896, vma_pages_left = 1024-896 = 128 > 128 < 128 (the condition is false), so _max_index stays ULONG_MAX > ra->start(1024) < ULONG_MAX, and it will prefetch pages 1024-1151 normally. This is exactly what we're trying to solve. > Page 1024 is already cached when VMA2 is entered, only minor fault happens. > > The key point: when mprotect splits a large file mapping into adjacent > VMAs (common for ELF segments, or read-then-write patterns), there's no > benefit in preventing readahead from crossing the boundary, so the data is > still sequential in the file. The limit only helps when we're actually > near the end of useful data (within ra_pages of the VMA end). This is completely missing the point. This change tried to back off from reading _anything_ past the VMA _on purpose_, due to ELF file spillage. This patch reintroduces spillage in a very obfuscated way. -- Pedro