On 11/6/26 06:18, Andrew Morton wrote:
> The second column assumes that the child touches all the file THPs,
> yes?  If the child touches only a small proportion of those mappings,
> or just does fork+exec, that changes the "Cost" comparison?

Yes. I measured it again on bare metal, with a fork()+exec column:
x86_64 with 4 NUMA nodes, the benchmark bound to node 0, both kernels
v7.4-rc1 with the same config, 4 GB of shmem THPs mapped MAP_PRIVATE
with an anon_vma, medians of 2000 forks, range over the rounds. The
exec is of /bin/true.

  +-----------------+------------+-----------------+--------------+
  | kernel          | fork()     | child reads all | fork()+exec  |
  +-----------------+------------+-----------------+--------------+
  | v7.4-rc1        | 135-141 us | 3820-4036 us    | 559-567 us   |
  | v7.4-rc1+series | 429-440 us | 1007-1036 us    | 1190-1226 us |
  +-----------------+------------+-----------------+--------------+

So a child that execs right away, or touches little, pays about 0.3 us
per huge PMD: the copy at fork and the teardown at exec or exit. A
child that faults a PMD in itself pays about 1.8 us for it, so the
copy wins once the child touches more than about a sixth of them.

> And on ppc64 hash-mode setups this also allocates deposited page tables
> for mappings which the child might never touch?  So a modest increase
> in memory use is to be expected?

Yes, but a small one, judging from the code (I have no ppc64 to test):
one 4 KB page table fragment per copied 16 MB PMD, 1/4096 of the
mapping. Radix and other arches deposit nothing.

It is freed when the child unmaps the range, execs or exits, and a PMD
the child faults in itself deposits the same 4 KB anyway.

> But I worry that this change is not an overall win for thp-file
> mappings, which are the common case.

Only a narrow case pays the extra cost, a file THP that is:

- mapped MAP_PRIVATE;
- in a VMA written to at least once, so it has an anon_vma;
- a PMD-sized folio in the page cache, mapped by one PMD;
- itself never written to.

For example:

- a big data file mapped MAP_PRIVATE that is mostly read and patched
  in a few places;
- a private mapping of a memfd or tmpfs file.

The common case does not get here. fork() skips a VMA without an
anon_vma and without VM_COPY_ON_FORK (vma_needs_copy()), so shared
file mappings and private ones that were never written are still left
to faults.

In these VMAs fork() already copies the PTEs of the same file folios;
only their PMDs were skipped.

> I'm not understanding why we need to mess with thp-file behavior at all
> in order to address a special-PMD bug?

It came from the review of v3: David asked to make copy_huge_pmd()
decide the way copy_present_ptes() does, instead of keeping rules of
its own for PMDs:

https://lore.kernel.org/all/[email protected]/

> Changelog is soooo long.  I replaced this Reproducer section with simply
>
>       - A reproducer is at the Link;

Sure, thanks. And thanks for the pmd_psize fixup.

--
Cheers,
Konstantin

Reply via email to