linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/9] mm/madvise: batch tlb flushes for MADV_DONTNEED and MADV_FREE
@ 2025-03-10 17:23 SeongJae Park
  2025-03-10 17:23 ` [PATCH 1/9] mm/madvise: use is_memory_failure() from madvise_do_behavior() SeongJae Park
                   ` (10 more replies)
  0 siblings, 11 replies; 42+ messages in thread
From: SeongJae Park @ 2025-03-10 17:23 UTC (permalink / raw)
  To: Andrew Morton
  Cc: SeongJae Park, Liam R. Howlett, David Hildenbrand,
	Lorenzo Stoakes, Shakeel Butt, Vlastimil Babka, kernel-team,
	linux-kernel, linux-mm

When process_madvise() is called to do MADV_DONTNEED[_LOCKED] or
MADV_FREE with multiple address ranges, tlb flushes happen for each of
the given address ranges.  Because such tlb flushes are for same
process, doing those in a batch is more efficient while still being
safe.  Modify process_madvise() entry level code path to do such batched
tlb flushes, while the internal unmap logics do only gathering of the
tlb entries to flush.

In more detail, modify the entry functions to initialize an mmu_gather
ojbect and pass it to the internal logics.  And make the internal logics
do only gathering of the tlb entries to flush into the received
mmu_gather object.  After all internal function calls are done, the
entry functions flush the gathered tlb entries at once.

The inefficiency should be smaller on madvise() use case, since it
receives only a single address range.  But if there are multiple vmas
for the range, same problem can happen.  It is unclear if such use case
is common and the inefficiency is significant.  Make the change for
madivse(), too, since it doesn't really change madvise() internal
behavior while helps keeping the code that shared between
process_madvise() and madvise() internal logics clean.

Patches Seuquence
=================

First four patches are minor cleanups of madvise.c for readability.

Fifth patch defines new data structure for managing information
that required for batched tlb flushes (mmu_gather and behavior), and
update code paths for MADV_DONTNEED[_LOCKED] and MADV_FREE handling
internal logics to receive it.

Sixth and seventh patches make internal logics for handling
MADV_DONTNEED[_LOCKED] MADV_FREE be ready for batched tlb flushing.  The
patches keep the support of unbatched tlb flushes use case, for
fine-grained and safe transitions.

Eighth patch updates madvise() and process_madvise() code to do the
batched tlb flushes utilizing the previous patches introduced changes.

The final ninth patch removes the internal logics' unbatched tlb flushes
use case support code, which is no more be used.

Test Results
============

I measured the latency to apply MADV_DONTNEED advice to 256 MiB memory
using multiple process_madvise() calls.  I apply the advice in 4 KiB
sized regions granularity, but with varying batch size per
process_madvise() call (vlen) from 1 to 1024.  The source code for the
measurement is available at GitHub[1].  To reduce measurement errors, I
did the measurement five times.

The measurement results are as below.  'sz_batch' column shows the batch
size of process_madvise() calls.  'Before' and 'After' columns show the
average of latencies in nanoseconds that measured five times on kernels
that built without and with the tlb flushes batching patch of this
series, respectively.  For the baseline, mm-unstable tree of
2025-03-07[2] has been used.  'B-stdev' and 'A-stdev' columns show
ratios of latency measurements standard deviation to average in percent
for 'Before' and 'After', respectively.  'Latency_reduction' shows the
reduction of the latency that the commit has achieved, in percent.
Higher 'Latency_reduction' values mean more efficiency improvements.

    sz_batch   Before        B-stdev   After         A-stdev   Latency_reduction
    1          128691595.4   6.09      106878698.4   2.76      16.95
    2          94046750.8    3.30      68691907      2.79      26.96
    4          80538496.8    5.35      50230673.8    5.30      37.63
    8          72672225.2    5.50      43918112      3.54      39.57
    16         66955104.4    4.25      36549941.2    1.62      45.41
    32         65814679      5.89      33060291      3.30      49.77
    64         65099205.2    2.69      26003756.4    1.56      60.06
    128        62591307.2    4.02      24008180.4    1.61      61.64
    256        64124368.6    2.93      23868856      2.20      62.78
    512        62325618      5.72      23311330.6    1.74      62.60
    1024       64802138.4    5.05      23651695.2    3.40      63.50

Interestingly, the latency has reduced (improved) even with batch size
1.  I think some of compiler optimizations have affected that, like also
observed with the previous process_madvise() mmap_lock optimization
patch sereis[3].

So, let's focus on the proportion between the improvement and the batch
size.  As expected, tlb flushes batching provides latency reduction that
proportional to the batch size.  The efficiency gain ranges from about
27 percent with batch size 2, and up to 63 percent with batch size
1,024.

Please note that this is a very simple microbenchmark, so real
efficiency gain on real workload could be very different.

Changes from RFC
(https://lore.kernel.org/20250305181611.54484-1-sj@kernel.org)
- Clarify motivation of the change on the cover letter
- Add average and stdev of evaluation results
- Show latency reduction on evaluation results
- Fix !CONFIG_MEMORY_FAILURE build error
- Rename is_memory_populate() to is_madvise_populate()
- Squash patches 5-8
- Add kerneldoc for unmap_vm_area_struct()
- Squash patches 10 and 11
- Squash patches 12-14
- Squash patches 15 and 16

References
==========

[1] https://github.com/sjp38/eval_proc_madvise
[2] commit e664d7d28a7c ("selftest: test system mappings are sealed") # mm-unstable
[3] https://lore.kernel.org/20250211182833.4193-1-sj@kernel.org

SeongJae Park (9):
  mm/madvise: use is_memory_failure() from madvise_do_behavior()
  mm/madvise: split out populate behavior check logic
  mm/madvise: deduplicate madvise_do_behavior() skip case handlings
  mm/madvise: remove len parameter of madvise_do_behavior()
  mm/madvise: define and use madvise_behavior struct for
    madvise_do_behavior()
  mm/memory: split non-tlb flushing part from zap_page_range_single()
  mm/madvise: let madvise_{dontneed,free}_single_vma() caller batches
    tlb flushes
  mm/madvise: batch tlb flushes for
    [process_]madvise(MADV_{DONTNEED[_LOCKED],FREE})
  mm/madvise: remove !tlb support from
    madvise_{dontneed,free}_single_vma()

 mm/internal.h |   3 +
 mm/madvise.c  | 221 +++++++++++++++++++++++++++++++++-----------------
 mm/memory.c   |  38 ++++++---
 3 files changed, 176 insertions(+), 86 deletions(-)


base-commit: e993f5f5b0ac851cf60578cfee5488031dfaa80c
-- 
2.39.5


^ permalink raw reply	[flat|nested] 42+ messages in thread

end of thread, other threads:[~2025-04-01 21:25 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-03-10 17:23 [PATCH 0/9] mm/madvise: batch tlb flushes for MADV_DONTNEED and MADV_FREE SeongJae Park
2025-03-10 17:23 ` [PATCH 1/9] mm/madvise: use is_memory_failure() from madvise_do_behavior() SeongJae Park
2025-03-11 11:27   ` Lorenzo Stoakes
2025-03-10 17:23 ` [PATCH 2/9] mm/madvise: split out populate behavior check logic SeongJae Park
2025-03-11 11:29   ` Lorenzo Stoakes
2025-03-10 17:23 ` [PATCH 3/9] mm/madvise: deduplicate madvise_do_behavior() skip case handlings SeongJae Park
2025-03-11 12:02   ` Lorenzo Stoakes
2025-03-11 20:54     ` SeongJae Park
2025-03-10 17:23 ` [PATCH 4/9] mm/madvise: remove len parameter of madvise_do_behavior() SeongJae Park
2025-03-11 12:05   ` Lorenzo Stoakes
2025-03-10 17:23 ` [PATCH 5/9] mm/madvise: define and use madvise_behavior struct for madvise_do_behavior() SeongJae Park
2025-03-11 12:17   ` Lorenzo Stoakes
2025-03-11 20:56     ` SeongJae Park
2025-03-12  5:47       ` Lorenzo Stoakes
2025-03-12 17:23         ` SeongJae Park
2025-03-10 17:23 ` [PATCH 6/9] mm/memory: split non-tlb flushing part from zap_page_range_single() SeongJae Park
2025-03-11 12:45   ` Lorenzo Stoakes
2025-03-11 20:58     ` SeongJae Park
2025-03-31 20:24       ` SeongJae Park
2025-04-01  1:45   ` Liam R. Howlett
2025-04-01  2:48     ` SeongJae Park
2025-04-01 14:03       ` Liam R. Howlett
2025-04-01 21:25         ` SeongJae Park
2025-03-10 17:23 ` [PATCH 7/9] mm/madvise: let madvise_{dontneed,free}_single_vma() caller batches tlb flushes SeongJae Park
2025-03-11 13:07   ` Lorenzo Stoakes
2025-03-11 21:00     ` SeongJae Park
2025-03-10 17:23 ` [PATCH 8/9] mm/madvise: batch tlb flushes for [process_]madvise(MADV_{DONTNEED[_LOCKED],FREE}) SeongJae Park
2025-03-11 13:59   ` Lorenzo Stoakes
2025-03-11 21:01     ` SeongJae Park
2025-04-01 21:17   ` SeongJae Park
2025-03-10 17:23 ` [PATCH 9/9] mm/madvise: remove !tlb support from madvise_{dontneed,free}_single_vma() SeongJae Park
2025-03-11 14:01   ` Lorenzo Stoakes
2025-03-11 21:02     ` SeongJae Park
2025-03-12 13:46       ` Lorenzo Stoakes
2025-04-01 21:22         ` SeongJae Park
2025-03-10 22:39 ` [PATCH 0/9] mm/madvise: batch tlb flushes for MADV_DONTNEED and MADV_FREE Andrew Morton
2025-03-10 23:15   ` Shakeel Butt
2025-03-10 23:36     ` Roman Gushchin
2025-03-11 11:17       ` Lorenzo Stoakes
2025-03-10 23:27   ` SeongJae Park
2025-03-11 12:49 ` Lorenzo Stoakes
2025-03-11 21:03   ` SeongJae Park

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox