All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Xu <peterx@redhat.com>
To: linux-mm@kvack.org, linux-kernel@vger.kernel.org
Cc: Huang Ying <ying.huang@intel.com>,
	Andrea Arcangeli <aarcange@redhat.com>,
	David Hildenbrand <david@redhat.com>,
	Minchan Kim <minchan@kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Vlastimil Babka <vbabka@suse.cz>,
	Nadav Amit <nadav.amit@gmail.com>,
	Hugh Dickins <hughd@google.com>,
	Andi Kleen <andi.kleen@intel.com>,
	peterx@redhat.com, "Kirill A . Shutemov" <kirill@shutemov.name>
Subject: [PATCH v2 0/2] mm: Remember a/d bits for migration entries
Date: Thu,  4 Aug 2022 16:39:50 -0400	[thread overview]
Message-ID: <20220804203952.53665-1-peterx@redhat.com> (raw)

v2:
- Fix build for !CONFIG_SWAP [syzbot]
- Carry over dirty bit too [Nadav]

rfc: https://lore.kernel.org/all/20220729014041.21292-1-peterx@redhat.com
v1:  https://lore.kernel.org/all/20220803012159.36551-1-peterx@redhat.com

Problem
=======

When migrate a page, right now we always mark the migrated page as old &
clean.

However that could lead to at least two problems:

  (1) We lost the real hot/cold information while we could have persisted.
      That information shouldn't change even if the backing page is changed
      after the migration,

  (2) There can be always extra overhead on the immediate next access to
      any migrated page, because hardware MMU needs cycles to set the young
      bit again for reads, and dirty bits for write, as long as the
      hardware MMU supports these bits.

Many of the recent upstream works showed that (2) is not something trivial
and actually very measurable.  In my test case, reading 1G chunk of memory
- jumping in page size intervals - could take 99ms just because of the
extra setting on the young bit on a generic x86_64 system, comparing to 4ms
if young set.

This issue is originally reported by Andrea Arcangeli.

Solution
========

To solve this problem, this patchset tries to remember the young/dirty bits
in the migration entries and carry them over when recovering the ptes.

We have the chance to do so because in many systems the swap offset is not
really fully used.  Migration entries use swp offset to store PFN only,
while the PFN is normally not as large as swp offset and normally smaller.
It means we do have some free bits in swp offset that we can use to store
things like A/D bits, and that's how this series tried to approach this
problem.

max_swapfile_size() is used here to detect per-arch offset length in swp
entries.  We'll automatically remember the A/D bits when we find that we
have enough swp offset field to keep both the PFN and the extra bits.

This series is majorly solving the bit lost issue only for the migration
procedure.  Besides that, a few topics to mention related to this series:

  (1) Page Idle Tracking

  Before this series, idle tracking can cause false negative if an accessed
  page got migrated, since after migration the young bit will get lost.
  After this series, it'll be better in that after migration young bit will
  be persisted, so it'll be able to be detected correctly by page idle
  logic when walking the pgtable.

  However there's still nothing done when page idle reset was carried out
  during migration procedure in progress, but that should be a separate
  topic to be addressed (e.g. to teach rmap pgtable walk code to be able to
  walk with both present ptes and migration ptes).

  (2) MADV_COLD/MADV_FREE

  This series doesn't teach madvise() code to recognize the new entries
  with reasons.

  Currently MADV_COLD is not handled for migration entries containing A
  bit.  Logically A bit should be dropped when colding a page, but here the
  more important thing is probably LRU operations which is still missing.
  It may justify that it is not a major scenario for COLD on migration
  entries.

  Similar thing applies to MADV_FREE: logically we should consider dropping
  migration entries as a whole if it is found.  In all cases, this series
  didn't cover any of the cases above assuming they'll be either kept as-is
  or be addressed in separate patchset.

Tests
=====

After the patchset applied, the immediate read access test [1] of above 1G
chunk after migration can shrink from 99ms to 4ms.  The test is done by
moving 1G pages from node 0->1->0 then read it in page size jumps.  The
test is with Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz.

Similar effect can also be measured when writting the memory the 1st time
after migration.

After applying the patchset, both initial immediate read/write after page
migrated will perform similarly like before migration happened.

Patch Layout
============

Patch 1:  Add swp_offset_pfn() and apply to all pfn swap entries, we should
          also stop treating swp_offset() as PFN anymore because it can
          contain more information starting from next patch.
Patch 2:  The core patch to remember young/dirty bit in swap offsets.

Please review, thanks.

[1] https://github.com/xzpeter/clibs/blob/master/misc/swap-young.c

Peter Xu (2):
  mm/swap: Add swp_offset_pfn() to fetch PFN from swap entry
  mm: Remember young/dirty bit for page migrations

 arch/arm64/mm/hugetlbpage.c |   2 +-
 include/linux/swapops.h     | 126 ++++++++++++++++++++++++++++++++++--
 mm/hmm.c                    |   2 +-
 mm/huge_memory.c            |  26 +++++++-
 mm/memory-failure.c         |   2 +-
 mm/migrate.c                |   6 +-
 mm/migrate_device.c         |   4 ++
 mm/page_vma_mapped.c        |   6 +-
 mm/rmap.c                   |   5 +-
 9 files changed, 163 insertions(+), 16 deletions(-)

-- 
2.32.0


             reply	other threads:[~2022-08-04 20:40 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-04 20:39 Peter Xu [this message]
2022-08-04 20:39 ` [PATCH v2 1/2] mm/swap: Add swp_offset_pfn() to fetch PFN from swap entry Peter Xu
2022-08-04 20:39 ` [PATCH v2 2/2] mm: Remember young/dirty bit for page migrations Peter Xu
2022-08-04 22:40   ` Nadav Amit
2022-08-05 16:30     ` Peter Xu
2022-08-09  8:45       ` Huang, Ying
2022-08-09  8:47         ` David Hildenbrand
2022-08-09 14:59         ` Peter Xu
2022-08-05 12:17   ` David Hildenbrand
2022-08-05 16:36     ` Peter Xu
2022-08-09  8:40   ` Huang, Ying
2022-08-09 17:59     ` Peter Xu
2022-08-10  0:53       ` Huang, Ying
2022-08-10 19:21         ` Peter Xu
2022-08-11  5:44           ` Alistair Popple
2022-08-04 22:17 ` [PATCH v2 0/2] mm: Remember a/d bits for migration entries Nadav Amit

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220804203952.53665-1-peterx@redhat.com \
    --to=peterx@redhat.com \
    --cc=aarcange@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=andi.kleen@intel.com \
    --cc=david@redhat.com \
    --cc=hughd@google.com \
    --cc=kirill@shutemov.name \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=minchan@kernel.org \
    --cc=nadav.amit@gmail.com \
    --cc=vbabka@suse.cz \
    --cc=ying.huang@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.