linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [RFC] Storing same-filled pages without a zswap_entry
@ 2024-03-20 20:49 Yosry Ahmed
  2024-03-20 21:07 ` Johannes Weiner
  2024-03-21  4:26 ` Chris Li
  0 siblings, 2 replies; 15+ messages in thread
From: Yosry Ahmed @ 2024-03-20 20:49 UTC (permalink / raw)
  To: Johannes Weiner, Nhat Pham, Chengming Zhou, Chris Li; +Cc: Linux-MM

Hey folks,

I was looking at cleaning up the same-filled handling code in zswap,
when it hit me that after the xarray conversion, the only member of
struct zwap_entry that is relevant to same-filled pages is now the
objcg pointer.

The xarray allows a pointer to be tagged by up to two tags (1 and 3),
so we can completely avoid allocating a zswap_entry for same-filled
pages by storing a tagged objcg pointer directly in the xarray
instead.

Basically the xarray would then either have a pointer to struct
zswap_entry or struct obj_cgroup, where the latter is tagged as
SAME_FILLED_ONE or SAME_FILLED_ZERO.

There are two benefits of this:
- Saving some memory (precisely 64 bytes per same-filled entry).
- Further separating handling of same-filled pages from compressed
pages, which results in some nice cleanups (especially in
zswap_store()). It also makes further improvements easier (e.g.
skipping limit checking for same-filled entries).

The disadvantage is obviously the complexity needed to handle two
different types of pointers in the xarray, although I think with the
correct abstractions this is not a big deal.

I have some untested patches that implement this that I plan on
testing and sending out at some point, the reason I am sending this
RFC now is to gauge interest. I am not sure how common same-filled
pages are. Unfortunately, this data is not easy to collect from our
fleet (still working on it), so if someone has data from actual
workloads that would be helpful.

Running the kernel build test only shows a small amount of same-filled
pages landing in zswap, but I am thinking maybe actual workloads have
more zerod pages lying around.


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

* Re: [RFC] Storing same-filled pages without a zswap_entry
  2024-03-20 20:49 [RFC] Storing same-filled pages without a zswap_entry Yosry Ahmed
@ 2024-03-20 21:07 ` Johannes Weiner
  2024-03-20 21:14   ` Yosry Ahmed
                     ` (2 more replies)
  2024-03-21  4:26 ` Chris Li
  1 sibling, 3 replies; 15+ messages in thread
From: Johannes Weiner @ 2024-03-20 21:07 UTC (permalink / raw)
  To: Yosry Ahmed; +Cc: Nhat Pham, Chengming Zhou, Chris Li, Linux-MM

On Wed, Mar 20, 2024 at 01:49:17PM -0700, Yosry Ahmed wrote:
> Hey folks,
> 
> I was looking at cleaning up the same-filled handling code in zswap,
> when it hit me that after the xarray conversion, the only member of
> struct zwap_entry that is relevant to same-filled pages is now the
> objcg pointer.
> 
> The xarray allows a pointer to be tagged by up to two tags (1 and 3),
> so we can completely avoid allocating a zswap_entry for same-filled
> pages by storing a tagged objcg pointer directly in the xarray
> instead.
> 
> Basically the xarray would then either have a pointer to struct
> zswap_entry or struct obj_cgroup, where the latter is tagged as
> SAME_FILLED_ONE or SAME_FILLED_ZERO.
> 
> There are two benefits of this:
> - Saving some memory (precisely 64 bytes per same-filled entry).
> - Further separating handling of same-filled pages from compressed
> pages, which results in some nice cleanups (especially in
> zswap_store()). It also makes further improvements easier (e.g.
> skipping limit checking for same-filled entries).

This sounds interesting.

Where would you store the byte value it's filled with? Or would you
limit it to zero-filled only?

> The disadvantage is obviously the complexity needed to handle two
> different types of pointers in the xarray, although I think with the
> correct abstractions this is not a big deal.
> 
> I have some untested patches that implement this that I plan on
> testing and sending out at some point, the reason I am sending this
> RFC now is to gauge interest. I am not sure how common same-filled
> pages are. Unfortunately, this data is not easy to collect from our
> fleet (still working on it), so if someone has data from actual
> workloads that would be helpful.
> 
> Running the kernel build test only shows a small amount of same-filled
> pages landing in zswap, but I am thinking maybe actual workloads have
> more zerod pages lying around.

In our fleet, same-filled pages seem to average pretty consistently at
10% of total stored entries.

I'd assume they're mostly zero-filled instead of other patterns, but I
don't have any data on that.

The savings from the entry would be a few megabytes per host, probably
not an argument by itself. But the code simplifications and shaving a
few cycles of the fast paths do sound promising.


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

* Re: [RFC] Storing same-filled pages without a zswap_entry
  2024-03-20 21:07 ` Johannes Weiner
@ 2024-03-20 21:14   ` Yosry Ahmed
  2024-03-20 21:19   ` Johannes Weiner
  2024-03-20 21:42   ` Chris Li
  2 siblings, 0 replies; 15+ messages in thread
From: Yosry Ahmed @ 2024-03-20 21:14 UTC (permalink / raw)
  To: Johannes Weiner; +Cc: Nhat Pham, Chengming Zhou, Chris Li, Linux-MM

On Wed, Mar 20, 2024 at 2:07 PM Johannes Weiner <hannes@cmpxchg.org> wrote:
>
> On Wed, Mar 20, 2024 at 01:49:17PM -0700, Yosry Ahmed wrote:
> > Hey folks,
> >
> > I was looking at cleaning up the same-filled handling code in zswap,
> > when it hit me that after the xarray conversion, the only member of
> > struct zwap_entry that is relevant to same-filled pages is now the
> > objcg pointer.
> >
> > The xarray allows a pointer to be tagged by up to two tags (1 and 3),
> > so we can completely avoid allocating a zswap_entry for same-filled
> > pages by storing a tagged objcg pointer directly in the xarray
> > instead.
> >
> > Basically the xarray would then either have a pointer to struct
> > zswap_entry or struct obj_cgroup, where the latter is tagged as
> > SAME_FILLED_ONE or SAME_FILLED_ZERO.
> >
> > There are two benefits of this:
> > - Saving some memory (precisely 64 bytes per same-filled entry).
> > - Further separating handling of same-filled pages from compressed
> > pages, which results in some nice cleanups (especially in
> > zswap_store()). It also makes further improvements easier (e.g.
> > skipping limit checking for same-filled entries).
>
> This sounds interesting.
>
> Where would you store the byte value it's filled with? Or would you
> limit it to zero-filled only?

Oh yeah I should have explicitly stated this, it would be limited to
pages filled with the same bit (all 0s or all 1s), assuming that most
same-filled entries would be zero-filled anyway.

>
> > The disadvantage is obviously the complexity needed to handle two
> > different types of pointers in the xarray, although I think with the
> > correct abstractions this is not a big deal.
> >
> > I have some untested patches that implement this that I plan on
> > testing and sending out at some point, the reason I am sending this
> > RFC now is to gauge interest. I am not sure how common same-filled
> > pages are. Unfortunately, this data is not easy to collect from our
> > fleet (still working on it), so if someone has data from actual
> > workloads that would be helpful.
> >
> > Running the kernel build test only shows a small amount of same-filled
> > pages landing in zswap, but I am thinking maybe actual workloads have
> > more zerod pages lying around.
>
> In our fleet, same-filled pages seem to average pretty consistently at
> 10% of total stored entries.
>
> I'd assume they're mostly zero-filled instead of other patterns, but I
> don't have any data on that.

I think this would be key to know if this is doable. If most
same-filled pages are zero pages, we can limit zswap's same-filled
feature for those and do the optimization. Otherwise we cannot do it,
as we actually store an entire word now as the same-filled "value".

Alternatively, we can have a separate struct that only has objcg and
value for same-filled pages. This means we still use 16 bytes (on
x86_64) per same-filled entry. I think we can still get the code
cleanups by separating handling for same-filled pages though?

>
> The savings from the entry would be a few megabytes per host, probably
> not an argument by itself. But the code simplifications and shaving a
> few cycles of the fast paths do sound promising.


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

* Re: [RFC] Storing same-filled pages without a zswap_entry
  2024-03-20 21:07 ` Johannes Weiner
  2024-03-20 21:14   ` Yosry Ahmed
@ 2024-03-20 21:19   ` Johannes Weiner
  2024-03-20 21:31     ` Yosry Ahmed
  2024-03-20 21:42   ` Chris Li
  2 siblings, 1 reply; 15+ messages in thread
From: Johannes Weiner @ 2024-03-20 21:19 UTC (permalink / raw)
  To: Yosry Ahmed; +Cc: Nhat Pham, Chengming Zhou, Chris Li, Linux-MM

On Wed, Mar 20, 2024 at 05:07:21PM -0400, Johannes Weiner wrote:
> On Wed, Mar 20, 2024 at 01:49:17PM -0700, Yosry Ahmed wrote:
> > Hey folks,
> > 
> > I was looking at cleaning up the same-filled handling code in zswap,
> > when it hit me that after the xarray conversion, the only member of
> > struct zwap_entry that is relevant to same-filled pages is now the
> > objcg pointer.
> > 
> > The xarray allows a pointer to be tagged by up to two tags (1 and 3),
> > so we can completely avoid allocating a zswap_entry for same-filled
> > pages by storing a tagged objcg pointer directly in the xarray
> > instead.
> > 
> > Basically the xarray would then either have a pointer to struct
> > zswap_entry or struct obj_cgroup, where the latter is tagged as
> > SAME_FILLED_ONE or SAME_FILLED_ZERO.
> > 
> > There are two benefits of this:
> > - Saving some memory (precisely 64 bytes per same-filled entry).
> > - Further separating handling of same-filled pages from compressed
> > pages, which results in some nice cleanups (especially in
> > zswap_store()). It also makes further improvements easier (e.g.
> > skipping limit checking for same-filled entries).
> 
> This sounds interesting.
> 
> Where would you store the byte value it's filled with? Or would you
> limit it to zero-filled only?

The dumb thing about objcg is that for same-filled entries we really
only need it for bumping ZSWPIN. Nothing else. entry->length is 0 for
them, so even though we call the charge function, it doesn't actually
do anything.

Loading them is cheap and doesn't involve decompression. An argument
could be made to exclude them from ZSWPOUT and ZSWPIN entirely.

Or cheat a little and bump ZSWPIN for current->objcg instead -
probably good enough to make excessive thrashing discoverable by the
workload that's directly affected.

Then you could get rid of the objcg pointer and use the xarray slot
for whatever else you'd want.


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

* Re: [RFC] Storing same-filled pages without a zswap_entry
  2024-03-20 21:19   ` Johannes Weiner
@ 2024-03-20 21:31     ` Yosry Ahmed
  2024-03-21  3:40       ` Chengming Zhou
  0 siblings, 1 reply; 15+ messages in thread
From: Yosry Ahmed @ 2024-03-20 21:31 UTC (permalink / raw)
  To: Johannes Weiner; +Cc: Nhat Pham, Chengming Zhou, Chris Li, Linux-MM

On Wed, Mar 20, 2024 at 2:19 PM Johannes Weiner <hannes@cmpxchg.org> wrote:
>
> On Wed, Mar 20, 2024 at 05:07:21PM -0400, Johannes Weiner wrote:
> > On Wed, Mar 20, 2024 at 01:49:17PM -0700, Yosry Ahmed wrote:
> > > Hey folks,
> > >
> > > I was looking at cleaning up the same-filled handling code in zswap,
> > > when it hit me that after the xarray conversion, the only member of
> > > struct zwap_entry that is relevant to same-filled pages is now the
> > > objcg pointer.
> > >
> > > The xarray allows a pointer to be tagged by up to two tags (1 and 3),
> > > so we can completely avoid allocating a zswap_entry for same-filled
> > > pages by storing a tagged objcg pointer directly in the xarray
> > > instead.
> > >
> > > Basically the xarray would then either have a pointer to struct
> > > zswap_entry or struct obj_cgroup, where the latter is tagged as
> > > SAME_FILLED_ONE or SAME_FILLED_ZERO.
> > >
> > > There are two benefits of this:
> > > - Saving some memory (precisely 64 bytes per same-filled entry).
> > > - Further separating handling of same-filled pages from compressed
> > > pages, which results in some nice cleanups (especially in
> > > zswap_store()). It also makes further improvements easier (e.g.
> > > skipping limit checking for same-filled entries).
> >
> > This sounds interesting.
> >
> > Where would you store the byte value it's filled with? Or would you
> > limit it to zero-filled only?
>
> The dumb thing about objcg is that for same-filled entries we really
> only need it for bumping ZSWPIN. Nothing else. entry->length is 0 for
> them, so even though we call the charge function, it doesn't actually
> do anything.
>
> Loading them is cheap and doesn't involve decompression. An argument
> could be made to exclude them from ZSWPOUT and ZSWPIN entirely.
>
> Or cheat a little and bump ZSWPIN for current->objcg instead -
> probably good enough to make excessive thrashing discoverable by the
> workload that's directly affected.
>
> Then you could get rid of the objcg pointer and use the xarray slot
> for whatever else you'd want.

Yeah it's only useful for the stats. Using current->objcg would work,
and should be ultimately pointing to the same memcg in *most* cases, I
assume. We still wouldn't be able to store a full word as we do today,
because the xarray needs 1 bit for its own usage. So the same-filled
implementation would still need to change from repeated words (8
bytes) to something smaller -- or we can just allocate a separate
struct for same-filled pages.


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

* Re: [RFC] Storing same-filled pages without a zswap_entry
  2024-03-20 21:07 ` Johannes Weiner
  2024-03-20 21:14   ` Yosry Ahmed
  2024-03-20 21:19   ` Johannes Weiner
@ 2024-03-20 21:42   ` Chris Li
  2 siblings, 0 replies; 15+ messages in thread
From: Chris Li @ 2024-03-20 21:42 UTC (permalink / raw)
  To: Johannes Weiner; +Cc: Yosry Ahmed, Nhat Pham, Chengming Zhou, Linux-MM

On Wed, Mar 20, 2024 at 2:07 PM Johannes Weiner <hannes@cmpxchg.org> wrote:
>
> On Wed, Mar 20, 2024 at 01:49:17PM -0700, Yosry Ahmed wrote:
> > Hey folks,
> >
> > I was looking at cleaning up the same-filled handling code in zswap,
> > when it hit me that after the xarray conversion, the only member of
> > struct zwap_entry that is relevant to same-filled pages is now the
> > objcg pointer.
> >
> > The xarray allows a pointer to be tagged by up to two tags (1 and 3),
> > so we can completely avoid allocating a zswap_entry for same-filled
> > pages by storing a tagged objcg pointer directly in the xarray
> > instead.
> >
> > Basically the xarray would then either have a pointer to struct
> > zswap_entry or struct obj_cgroup, where the latter is tagged as
> > SAME_FILLED_ONE or SAME_FILLED_ZERO.
> >
> > There are two benefits of this:
> > - Saving some memory (precisely 64 bytes per same-filled entry).
> > - Further separating handling of same-filled pages from compressed
> > pages, which results in some nice cleanups (especially in
> > zswap_store()). It also makes further improvements easier (e.g.
> > skipping limit checking for same-filled entries).
>
> This sounds interesting.
>
> Where would you store the byte value it's filled with? Or would you
> limit it to zero-filled only?
>
> > The disadvantage is obviously the complexity needed to handle two
> > different types of pointers in the xarray, although I think with the
> > correct abstractions this is not a big deal.
> >
> > I have some untested patches that implement this that I plan on
> > testing and sending out at some point, the reason I am sending this
> > RFC now is to gauge interest. I am not sure how common same-filled
> > pages are. Unfortunately, this data is not easy to collect from our
> > fleet (still working on it), so if someone has data from actual
> > workloads that would be helpful.
> >
> > Running the kernel build test only shows a small amount of same-filled
> > pages landing in zswap, but I am thinking maybe actual workloads have
> > more zerod pages lying around.
>
> In our fleet, same-filled pages seem to average pretty consistently at
> 10% of total stored entries.
>
> I'd assume they're mostly zero-filled instead of other patterns, but I
> don't have any data on that.

That matches with my experience. All of them are just zero fill pages
for the kdump that I have looked at. It is about a few thousand of
zero fill pages if I remember correctly.

Chris


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

* Re: [RFC] Storing same-filled pages without a zswap_entry
  2024-03-20 21:31     ` Yosry Ahmed
@ 2024-03-21  3:40       ` Chengming Zhou
  2024-03-21 18:44         ` Yosry Ahmed
  0 siblings, 1 reply; 15+ messages in thread
From: Chengming Zhou @ 2024-03-21  3:40 UTC (permalink / raw)
  To: Yosry Ahmed, Johannes Weiner; +Cc: Nhat Pham, Chris Li, Linux-MM

On 2024/3/21 05:31, Yosry Ahmed wrote:
> On Wed, Mar 20, 2024 at 2:19 PM Johannes Weiner <hannes@cmpxchg.org> wrote:
>>
>> On Wed, Mar 20, 2024 at 05:07:21PM -0400, Johannes Weiner wrote:
>>> On Wed, Mar 20, 2024 at 01:49:17PM -0700, Yosry Ahmed wrote:
>>>> Hey folks,
>>>>
>>>> I was looking at cleaning up the same-filled handling code in zswap,
>>>> when it hit me that after the xarray conversion, the only member of
>>>> struct zwap_entry that is relevant to same-filled pages is now the
>>>> objcg pointer.
>>>>
>>>> The xarray allows a pointer to be tagged by up to two tags (1 and 3),
>>>> so we can completely avoid allocating a zswap_entry for same-filled
>>>> pages by storing a tagged objcg pointer directly in the xarray
>>>> instead.
>>>>
>>>> Basically the xarray would then either have a pointer to struct
>>>> zswap_entry or struct obj_cgroup, where the latter is tagged as
>>>> SAME_FILLED_ONE or SAME_FILLED_ZERO.
>>>>
>>>> There are two benefits of this:
>>>> - Saving some memory (precisely 64 bytes per same-filled entry).
>>>> - Further separating handling of same-filled pages from compressed
>>>> pages, which results in some nice cleanups (especially in
>>>> zswap_store()). It also makes further improvements easier (e.g.
>>>> skipping limit checking for same-filled entries).

I also think this is a good idea. :) Which could simplify the code too.

>>>
>>> This sounds interesting.
>>>
>>> Where would you store the byte value it's filled with? Or would you
>>> limit it to zero-filled only?
>>
>> The dumb thing about objcg is that for same-filled entries we really
>> only need it for bumping ZSWPIN. Nothing else. entry->length is 0 for
>> them, so even though we call the charge function, it doesn't actually
>> do anything.
>>
>> Loading them is cheap and doesn't involve decompression. An argument
>> could be made to exclude them from ZSWPOUT and ZSWPIN entirely.
>>
>> Or cheat a little and bump ZSWPIN for current->objcg instead -
>> probably good enough to make excessive thrashing discoverable by the
>> workload that's directly affected.
>>
>> Then you could get rid of the objcg pointer and use the xarray slot
>> for whatever else you'd want.
> 
> Yeah it's only useful for the stats. Using current->objcg would work,
> and should be ultimately pointing to the same memcg in *most* cases, I

In some cases where the current objcg is not "correct", the testcases in
test_zswap.c may break? Maybe we can use swap_cgroup info to charge the
stats to the correct memcg? Not sure if this is feasible.

> assume. We still wouldn't be able to store a full word as we do today,
> because the xarray needs 1 bit for its own usage. So the same-filled
> implementation would still need to change from repeated words (8
> bytes) to something smaller -- or we can just allocate a separate
> struct for same-filled pages.

Yes, this seems an unavoidable limit of value in xarray...

Thanks.


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

* Re: [RFC] Storing same-filled pages without a zswap_entry
  2024-03-20 20:49 [RFC] Storing same-filled pages without a zswap_entry Yosry Ahmed
  2024-03-20 21:07 ` Johannes Weiner
@ 2024-03-21  4:26 ` Chris Li
  2024-03-21 18:50   ` Yosry Ahmed
  1 sibling, 1 reply; 15+ messages in thread
From: Chris Li @ 2024-03-21  4:26 UTC (permalink / raw)
  To: Yosry Ahmed; +Cc: Johannes Weiner, Nhat Pham, Chengming Zhou, Linux-MM

On Wed, Mar 20, 2024 at 1:49 PM Yosry Ahmed <yosryahmed@google.com> wrote:
>
> Hey folks,
>
> I was looking at cleaning up the same-filled handling code in zswap,
> when it hit me that after the xarray conversion, the only member of
> struct zwap_entry that is relevant to same-filled pages is now the
> objcg pointer.
>
> The xarray allows a pointer to be tagged by up to two tags (1 and 3),
> so we can completely avoid allocating a zswap_entry for same-filled
> pages by storing a tagged objcg pointer directly in the xarray
> instead.
>
> Basically the xarray would then either have a pointer to struct
> zswap_entry or struct obj_cgroup, where the latter is tagged as
> SAME_FILLED_ONE or SAME_FILLED_ZERO.
>
> There are two benefits of this:
> - Saving some memory (precisely 64 bytes per same-filled entry).
> - Further separating handling of same-filled pages from compressed
> pages, which results in some nice cleanups (especially in
> zswap_store()). It also makes further improvements easier (e.g.
> skipping limit checking for same-filled entries).
>
> The disadvantage is obviously the complexity needed to handle two
> different types of pointers in the xarray, although I think with the
> correct abstractions this is not a big deal.

Another idea is we can make the zero fill zswap entry immutable and
share by different pages. That way it does not depend on the xarray
pointer tagging. It can share the same code path with existing zero
fill page handling. Just don't free the zero fill entry.

I want to reserve the zswap xarray tagging for another purpose.

Just some food for thought. Might have less complexity because it
doesn't need to deal with two different kinds of pointers.

Chris


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

* Re: [RFC] Storing same-filled pages without a zswap_entry
  2024-03-21  3:40       ` Chengming Zhou
@ 2024-03-21 18:44         ` Yosry Ahmed
  2024-03-21 19:29           ` Johannes Weiner
  0 siblings, 1 reply; 15+ messages in thread
From: Yosry Ahmed @ 2024-03-21 18:44 UTC (permalink / raw)
  To: Chengming Zhou; +Cc: Johannes Weiner, Nhat Pham, Chris Li, Linux-MM

On Thu, Mar 21, 2024 at 11:40:32AM +0800, Chengming Zhou wrote:
> On 2024/3/21 05:31, Yosry Ahmed wrote:
> > On Wed, Mar 20, 2024 at 2:19 PM Johannes Weiner <hannes@cmpxchg.org> wrote:
> >>
> >> On Wed, Mar 20, 2024 at 05:07:21PM -0400, Johannes Weiner wrote:
> >>> On Wed, Mar 20, 2024 at 01:49:17PM -0700, Yosry Ahmed wrote:
> >>>> Hey folks,
> >>>>
> >>>> I was looking at cleaning up the same-filled handling code in zswap,
> >>>> when it hit me that after the xarray conversion, the only member of
> >>>> struct zwap_entry that is relevant to same-filled pages is now the
> >>>> objcg pointer.
> >>>>
> >>>> The xarray allows a pointer to be tagged by up to two tags (1 and 3),
> >>>> so we can completely avoid allocating a zswap_entry for same-filled
> >>>> pages by storing a tagged objcg pointer directly in the xarray
> >>>> instead.
> >>>>
> >>>> Basically the xarray would then either have a pointer to struct
> >>>> zswap_entry or struct obj_cgroup, where the latter is tagged as
> >>>> SAME_FILLED_ONE or SAME_FILLED_ZERO.
> >>>>
> >>>> There are two benefits of this:
> >>>> - Saving some memory (precisely 64 bytes per same-filled entry).
> >>>> - Further separating handling of same-filled pages from compressed
> >>>> pages, which results in some nice cleanups (especially in
> >>>> zswap_store()). It also makes further improvements easier (e.g.
> >>>> skipping limit checking for same-filled entries).
> 
> I also think this is a good idea. :) Which could simplify the code too.
> 
> >>>
> >>> This sounds interesting.
> >>>
> >>> Where would you store the byte value it's filled with? Or would you
> >>> limit it to zero-filled only?
> >>
> >> The dumb thing about objcg is that for same-filled entries we really
> >> only need it for bumping ZSWPIN. Nothing else. entry->length is 0 for
> >> them, so even though we call the charge function, it doesn't actually
> >> do anything.
> >>
> >> Loading them is cheap and doesn't involve decompression. An argument
> >> could be made to exclude them from ZSWPOUT and ZSWPIN entirely.
> >>
> >> Or cheat a little and bump ZSWPIN for current->objcg instead -
> >> probably good enough to make excessive thrashing discoverable by the
> >> workload that's directly affected.
> >>
> >> Then you could get rid of the objcg pointer and use the xarray slot
> >> for whatever else you'd want.
> > 
> > Yeah it's only useful for the stats. Using current->objcg would work,
> > and should be ultimately pointing to the same memcg in *most* cases, I
> 
> In some cases where the current objcg is not "correct", the testcases in
> test_zswap.c may break? Maybe we can use swap_cgroup info to charge the
> stats to the correct memcg? Not sure if this is feasible.

For cgroup v1, swap_cgroup will be cleared from
mem_cgroup_swapin_uncharge_swap() before the zswap load.

I think the current objcg will remain correct as long as swapin happens
from the same memcg as swapout (or if swapin happens from the parent
memcg and the swapout memcg was offlined).


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

* Re: [RFC] Storing same-filled pages without a zswap_entry
  2024-03-21  4:26 ` Chris Li
@ 2024-03-21 18:50   ` Yosry Ahmed
  2024-03-22  0:18     ` Chris Li
  0 siblings, 1 reply; 15+ messages in thread
From: Yosry Ahmed @ 2024-03-21 18:50 UTC (permalink / raw)
  To: Chris Li; +Cc: Johannes Weiner, Nhat Pham, Chengming Zhou, Linux-MM

On Wed, Mar 20, 2024 at 09:26:43PM -0700, Chris Li wrote:
> On Wed, Mar 20, 2024 at 1:49 PM Yosry Ahmed <yosryahmed@google.com> wrote:
> >
> > Hey folks,
> >
> > I was looking at cleaning up the same-filled handling code in zswap,
> > when it hit me that after the xarray conversion, the only member of
> > struct zwap_entry that is relevant to same-filled pages is now the
> > objcg pointer.
> >
> > The xarray allows a pointer to be tagged by up to two tags (1 and 3),
> > so we can completely avoid allocating a zswap_entry for same-filled
> > pages by storing a tagged objcg pointer directly in the xarray
> > instead.
> >
> > Basically the xarray would then either have a pointer to struct
> > zswap_entry or struct obj_cgroup, where the latter is tagged as
> > SAME_FILLED_ONE or SAME_FILLED_ZERO.
> >
> > There are two benefits of this:
> > - Saving some memory (precisely 64 bytes per same-filled entry).
> > - Further separating handling of same-filled pages from compressed
> > pages, which results in some nice cleanups (especially in
> > zswap_store()). It also makes further improvements easier (e.g.
> > skipping limit checking for same-filled entries).
> >
> > The disadvantage is obviously the complexity needed to handle two
> > different types of pointers in the xarray, although I think with the
> > correct abstractions this is not a big deal.
> 
> Another idea is we can make the zero fill zswap entry immutable and
> share by different pages. That way it does not depend on the xarray
> pointer tagging. It can share the same code path with existing zero
> fill page handling. Just don't free the zero fill entry.

The only relevant item in zswap_entry for same-filled pages is objcg.
That cannot be shared by different pages anyway. So basically the
immutable zswap entry will just be a magic value that encodes all
zero-filled pages.

If we are all fine with only supporting zero-filled pages, then I don't
see why we should not just store the objcg in the xarray and tag it as
such. In fact, we only need to use one of the two available tags in this
case.

> 
> I want to reserve the zswap xarray tagging for another purpose.

Did you have another purpose in mind? or just for future expansion?

As I mentioned above, if we only support zero-filled pages, we only need
one of the two available tags. Also, this is an in-kernel change so I
think we could always take it back if we really need the tags in the
future.

> 
> Just some food for thought. Might have less complexity because it
> doesn't need to deal with two different kinds of pointers.

I think the complexity is not that much with the right abstractions, but
this is best discussed with actual code imo.

> 
> Chris
> 


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

* Re: [RFC] Storing same-filled pages without a zswap_entry
  2024-03-21 18:44         ` Yosry Ahmed
@ 2024-03-21 19:29           ` Johannes Weiner
  2024-03-21 19:57             ` Yosry Ahmed
  0 siblings, 1 reply; 15+ messages in thread
From: Johannes Weiner @ 2024-03-21 19:29 UTC (permalink / raw)
  To: Yosry Ahmed; +Cc: Chengming Zhou, Nhat Pham, Chris Li, Linux-MM

On Thu, Mar 21, 2024 at 06:44:54PM +0000, Yosry Ahmed wrote:
> On Thu, Mar 21, 2024 at 11:40:32AM +0800, Chengming Zhou wrote:
> > On 2024/3/21 05:31, Yosry Ahmed wrote:
> > > On Wed, Mar 20, 2024 at 2:19 PM Johannes Weiner <hannes@cmpxchg.org> wrote:
> > >>
> > >> On Wed, Mar 20, 2024 at 05:07:21PM -0400, Johannes Weiner wrote:
> > >>> On Wed, Mar 20, 2024 at 01:49:17PM -0700, Yosry Ahmed wrote:
> > >>>> Hey folks,
> > >>>>
> > >>>> I was looking at cleaning up the same-filled handling code in zswap,
> > >>>> when it hit me that after the xarray conversion, the only member of
> > >>>> struct zwap_entry that is relevant to same-filled pages is now the
> > >>>> objcg pointer.
> > >>>>
> > >>>> The xarray allows a pointer to be tagged by up to two tags (1 and 3),
> > >>>> so we can completely avoid allocating a zswap_entry for same-filled
> > >>>> pages by storing a tagged objcg pointer directly in the xarray
> > >>>> instead.
> > >>>>
> > >>>> Basically the xarray would then either have a pointer to struct
> > >>>> zswap_entry or struct obj_cgroup, where the latter is tagged as
> > >>>> SAME_FILLED_ONE or SAME_FILLED_ZERO.
> > >>>>
> > >>>> There are two benefits of this:
> > >>>> - Saving some memory (precisely 64 bytes per same-filled entry).
> > >>>> - Further separating handling of same-filled pages from compressed
> > >>>> pages, which results in some nice cleanups (especially in
> > >>>> zswap_store()). It also makes further improvements easier (e.g.
> > >>>> skipping limit checking for same-filled entries).
> > 
> > I also think this is a good idea. :) Which could simplify the code too.
> > 
> > >>>
> > >>> This sounds interesting.
> > >>>
> > >>> Where would you store the byte value it's filled with? Or would you
> > >>> limit it to zero-filled only?
> > >>
> > >> The dumb thing about objcg is that for same-filled entries we really
> > >> only need it for bumping ZSWPIN. Nothing else. entry->length is 0 for
> > >> them, so even though we call the charge function, it doesn't actually
> > >> do anything.
> > >>
> > >> Loading them is cheap and doesn't involve decompression. An argument
> > >> could be made to exclude them from ZSWPOUT and ZSWPIN entirely.
> > >>
> > >> Or cheat a little and bump ZSWPIN for current->objcg instead -
> > >> probably good enough to make excessive thrashing discoverable by the
> > >> workload that's directly affected.
> > >>
> > >> Then you could get rid of the objcg pointer and use the xarray slot
> > >> for whatever else you'd want.
> > > 
> > > Yeah it's only useful for the stats. Using current->objcg would work,
> > > and should be ultimately pointing to the same memcg in *most* cases, I
> > 
> > In some cases where the current objcg is not "correct", the testcases in
> > test_zswap.c may break? Maybe we can use swap_cgroup info to charge the
> > stats to the correct memcg? Not sure if this is feasible.
> 
> For cgroup v1, swap_cgroup will be cleared from
> mem_cgroup_swapin_uncharge_swap() before the zswap load.
> 
> I think the current objcg will remain correct as long as swapin happens
> from the same memcg as swapout (or if swapin happens from the parent
> memcg and the swapout memcg was offlined).

Swap readahead will pull in physically adjacent entries that may
belong to somebody unrelated.



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

* Re: [RFC] Storing same-filled pages without a zswap_entry
  2024-03-21 19:29           ` Johannes Weiner
@ 2024-03-21 19:57             ` Yosry Ahmed
  2024-03-22  0:28               ` Chris Li
  0 siblings, 1 reply; 15+ messages in thread
From: Yosry Ahmed @ 2024-03-21 19:57 UTC (permalink / raw)
  To: Johannes Weiner; +Cc: Chengming Zhou, Nhat Pham, Chris Li, Linux-MM

On Thu, Mar 21, 2024 at 12:29 PM Johannes Weiner <hannes@cmpxchg.org> wrote:
>
> On Thu, Mar 21, 2024 at 06:44:54PM +0000, Yosry Ahmed wrote:
> > On Thu, Mar 21, 2024 at 11:40:32AM +0800, Chengming Zhou wrote:
> > > On 2024/3/21 05:31, Yosry Ahmed wrote:
> > > > On Wed, Mar 20, 2024 at 2:19 PM Johannes Weiner <hannes@cmpxchg.org> wrote:
> > > >>
> > > >> On Wed, Mar 20, 2024 at 05:07:21PM -0400, Johannes Weiner wrote:
> > > >>> On Wed, Mar 20, 2024 at 01:49:17PM -0700, Yosry Ahmed wrote:
> > > >>>> Hey folks,
> > > >>>>
> > > >>>> I was looking at cleaning up the same-filled handling code in zswap,
> > > >>>> when it hit me that after the xarray conversion, the only member of
> > > >>>> struct zwap_entry that is relevant to same-filled pages is now the
> > > >>>> objcg pointer.
> > > >>>>
> > > >>>> The xarray allows a pointer to be tagged by up to two tags (1 and 3),
> > > >>>> so we can completely avoid allocating a zswap_entry for same-filled
> > > >>>> pages by storing a tagged objcg pointer directly in the xarray
> > > >>>> instead.
> > > >>>>
> > > >>>> Basically the xarray would then either have a pointer to struct
> > > >>>> zswap_entry or struct obj_cgroup, where the latter is tagged as
> > > >>>> SAME_FILLED_ONE or SAME_FILLED_ZERO.
> > > >>>>
> > > >>>> There are two benefits of this:
> > > >>>> - Saving some memory (precisely 64 bytes per same-filled entry).
> > > >>>> - Further separating handling of same-filled pages from compressed
> > > >>>> pages, which results in some nice cleanups (especially in
> > > >>>> zswap_store()). It also makes further improvements easier (e.g.
> > > >>>> skipping limit checking for same-filled entries).
> > >
> > > I also think this is a good idea. :) Which could simplify the code too.
> > >
> > > >>>
> > > >>> This sounds interesting.
> > > >>>
> > > >>> Where would you store the byte value it's filled with? Or would you
> > > >>> limit it to zero-filled only?
> > > >>
> > > >> The dumb thing about objcg is that for same-filled entries we really
> > > >> only need it for bumping ZSWPIN. Nothing else. entry->length is 0 for
> > > >> them, so even though we call the charge function, it doesn't actually
> > > >> do anything.
> > > >>
> > > >> Loading them is cheap and doesn't involve decompression. An argument
> > > >> could be made to exclude them from ZSWPOUT and ZSWPIN entirely.
> > > >>
> > > >> Or cheat a little and bump ZSWPIN for current->objcg instead -
> > > >> probably good enough to make excessive thrashing discoverable by the
> > > >> workload that's directly affected.
> > > >>
> > > >> Then you could get rid of the objcg pointer and use the xarray slot
> > > >> for whatever else you'd want.
> > > >
> > > > Yeah it's only useful for the stats. Using current->objcg would work,
> > > > and should be ultimately pointing to the same memcg in *most* cases, I
> > >
> > > In some cases where the current objcg is not "correct", the testcases in
> > > test_zswap.c may break? Maybe we can use swap_cgroup info to charge the
> > > stats to the correct memcg? Not sure if this is feasible.
> >
> > For cgroup v1, swap_cgroup will be cleared from
> > mem_cgroup_swapin_uncharge_swap() before the zswap load.
> >
> > I think the current objcg will remain correct as long as swapin happens
> > from the same memcg as swapout (or if swapin happens from the parent
> > memcg and the swapout memcg was offlined).
>
> Swap readahead will pull in physically adjacent entries that may
> belong to somebody unrelated.

Right. For those as well the current objcg would be correct if they
are readahead from the same memcg as the one they were swapped out
from, but I understand your point that readahead makes that more
likely to not be the case.

I am slightly nervous about using the current objcg tbh, even though
it only affects the stats. It's just less straightforward this way. I
think I prefer either:
(a) Only supporting zero-filled pages and storing the objcg directly
in the xarray.
(b) Having a separate two-word struct to store objcg and value for
same-filled pages.

In both cases, we would need one tag bit to identify same-filled pages
in the xarray. (a) is more tempting for me, but I am not sure everyone
else agrees with dropping support for non-zero same-filled pages.


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

* Re: [RFC] Storing same-filled pages without a zswap_entry
  2024-03-21 18:50   ` Yosry Ahmed
@ 2024-03-22  0:18     ` Chris Li
  0 siblings, 0 replies; 15+ messages in thread
From: Chris Li @ 2024-03-22  0:18 UTC (permalink / raw)
  To: Yosry Ahmed; +Cc: Johannes Weiner, Nhat Pham, Chengming Zhou, Linux-MM

On Thu, Mar 21, 2024 at 11:50 AM Yosry Ahmed <yosryahmed@google.com> wrote:
>
> On Wed, Mar 20, 2024 at 09:26:43PM -0700, Chris Li wrote:
>
> >
> > Another idea is we can make the zero fill zswap entry immutable and
> > share by different pages. That way it does not depend on the xarray
> > pointer tagging. It can share the same code path with existing zero
> > fill page handling. Just don't free the zero fill entry.
>
> The only relevant item in zswap_entry for same-filled pages is objcg.
> That cannot be shared by different pages anyway. So basically the

Ah, good points about the objcg can't be shared.

Chris


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

* Re: [RFC] Storing same-filled pages without a zswap_entry
  2024-03-21 19:57             ` Yosry Ahmed
@ 2024-03-22  0:28               ` Chris Li
  2024-03-22  0:37                 ` Yosry Ahmed
  0 siblings, 1 reply; 15+ messages in thread
From: Chris Li @ 2024-03-22  0:28 UTC (permalink / raw)
  To: Yosry Ahmed; +Cc: Johannes Weiner, Chengming Zhou, Nhat Pham, Linux-MM

On Thu, Mar 21, 2024 at 12:58 PM Yosry Ahmed <yosryahmed@google.com> wrote:
>
> On Thu, Mar 21, 2024 at 12:29 PM Johannes Weiner <hannes@cmpxchg.org> wrote:
> >
> > On Thu, Mar 21, 2024 at 06:44:54PM +0000, Yosry Ahmed wrote:
> > > > In some cases where the current objcg is not "correct", the testcases in
> > > > test_zswap.c may break? Maybe we can use swap_cgroup info to charge the
> > > > stats to the correct memcg? Not sure if this is feasible.
> > >
> > > For cgroup v1, swap_cgroup will be cleared from
> > > mem_cgroup_swapin_uncharge_swap() before the zswap load.
> > >
> > > I think the current objcg will remain correct as long as swapin happens
> > > from the same memcg as swapout (or if swapin happens from the parent
> > > memcg and the swapout memcg was offlined).
> >
> > Swap readahead will pull in physically adjacent entries that may
> > belong to somebody unrelated.
>
> Right. For those as well the current objcg would be correct if they
> are readahead from the same memcg as the one they were swapped out
> from, but I understand your point that readahead makes that more
> likely to not be the case.
>
> I am slightly nervous about using the current objcg tbh, even though
> it only affects the stats. It's just less straightforward this way. I
> think I prefer either:
> (a) Only supporting zero-filled pages and storing the objcg directly
> in the xarray.

We can add the zero-filled page as a special case to speed it up. I
don't think we should remove non zero values of the same fill pages
from zswap though. We can never declare the non zero same filled page
is not going to happen. In that case, the current same fill is still
better than going through the zsmalloc.

Chris

> (b) Having a separate two-word struct to store objcg and value for
> same-filled pages.
>
> In both cases, we would need one tag bit to identify same-filled pages
> in the xarray. (a) is more tempting for me, but I am not sure everyone
> else agrees with dropping support for non-zero same-filled pages.


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

* Re: [RFC] Storing same-filled pages without a zswap_entry
  2024-03-22  0:28               ` Chris Li
@ 2024-03-22  0:37                 ` Yosry Ahmed
  0 siblings, 0 replies; 15+ messages in thread
From: Yosry Ahmed @ 2024-03-22  0:37 UTC (permalink / raw)
  To: Chris Li; +Cc: Johannes Weiner, Chengming Zhou, Nhat Pham, Linux-MM

On Thu, Mar 21, 2024 at 5:29 PM Chris Li <chrisl@kernel.org> wrote:
>
> On Thu, Mar 21, 2024 at 12:58 PM Yosry Ahmed <yosryahmed@google.com> wrote:
> >
> > On Thu, Mar 21, 2024 at 12:29 PM Johannes Weiner <hannes@cmpxchg.org> wrote:
> > >
> > > On Thu, Mar 21, 2024 at 06:44:54PM +0000, Yosry Ahmed wrote:
> > > > > In some cases where the current objcg is not "correct", the testcases in
> > > > > test_zswap.c may break? Maybe we can use swap_cgroup info to charge the
> > > > > stats to the correct memcg? Not sure if this is feasible.
> > > >
> > > > For cgroup v1, swap_cgroup will be cleared from
> > > > mem_cgroup_swapin_uncharge_swap() before the zswap load.
> > > >
> > > > I think the current objcg will remain correct as long as swapin happens
> > > > from the same memcg as swapout (or if swapin happens from the parent
> > > > memcg and the swapout memcg was offlined).
> > >
> > > Swap readahead will pull in physically adjacent entries that may
> > > belong to somebody unrelated.
> >
> > Right. For those as well the current objcg would be correct if they
> > are readahead from the same memcg as the one they were swapped out
> > from, but I understand your point that readahead makes that more
> > likely to not be the case.
> >
> > I am slightly nervous about using the current objcg tbh, even though
> > it only affects the stats. It's just less straightforward this way. I
> > think I prefer either:
> > (a) Only supporting zero-filled pages and storing the objcg directly
> > in the xarray.
>
> We can add the zero-filled page as a special case to speed it up. I
> don't think we should remove non zero values of the same fill pages
> from zswap though. We can never declare the non zero same filled page
> is not going to happen. In that case, the current same fill is still
> better than going through the zsmalloc.

If we do this, we still need to support same-filled entries in
zswap_entry, which means we still cannot separate the logic
completely. Also, it would be weird to have zero-filled pages and
same-filled pages handled differently.

How common do we think same-filled but not zero-filled pages are? Are
there known user space usages or patterns that lead to this? The only
thing I can think of is if user space initializes a large array to the
same non-zero value, and then it gets swapped out before it is
modified.

If it is not common, perhaps it's not worth optimizing it.


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

end of thread, other threads:[~2024-03-22  0:38 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-20 20:49 [RFC] Storing same-filled pages without a zswap_entry Yosry Ahmed
2024-03-20 21:07 ` Johannes Weiner
2024-03-20 21:14   ` Yosry Ahmed
2024-03-20 21:19   ` Johannes Weiner
2024-03-20 21:31     ` Yosry Ahmed
2024-03-21  3:40       ` Chengming Zhou
2024-03-21 18:44         ` Yosry Ahmed
2024-03-21 19:29           ` Johannes Weiner
2024-03-21 19:57             ` Yosry Ahmed
2024-03-22  0:28               ` Chris Li
2024-03-22  0:37                 ` Yosry Ahmed
2024-03-20 21:42   ` Chris Li
2024-03-21  4:26 ` Chris Li
2024-03-21 18:50   ` Yosry Ahmed
2024-03-22  0:18     ` Chris Li

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