Skip to content

Store object age in a bitmap #7938

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 13, 2023

Conversation

eightbitraptor
Copy link
Contributor

Previously 2 bits of the flags on each RVALUE are reserved to store the number of GC cycles that each object has survived. This commit introduces a new bit array on the heap page, called age_bits, to store that information instead.

This patch still reserves one of the age bits in the flags (the old FL_PROMOTED0 bit, now renamed FL_PROMOTED).

This is set to 0 for young objects and 1 for old objects, and is used as a performance optimisation for the write barrier. Fetching the age_bits from the heap page and doing the required math to calculate if the object was old or not would slow down the write barrier. So we keep this bit synced in the flags for fast access.

@matzbot matzbot requested a review from a team June 13, 2023 13:45
@eightbitraptor eightbitraptor force-pushed the mvh-rvalue-age-bitmap branch from 6a84634 to 7696a6f Compare June 13, 2023 13:49
@eightbitraptor eightbitraptor force-pushed the mvh-rvalue-age-bitmap branch from 7696a6f to 9fbc7cc Compare June 13, 2023 14:15
@maximecb
Copy link
Contributor

This is set to 0 for young objects and 1 for old objects, and is used as a performance optimisation for the write barrier. Fetching the age_bits from the heap page and doing the required math to calculate if the object was old or not would slow down the write barrier. So we keep this bit synced in the flags for fast access.

Given that accessing these bits from the heap adds extra performance overhead, can you provide more background as to why these bits are being maintained in a separate location in addition to the flag bits?

@eightbitraptor eightbitraptor force-pushed the mvh-rvalue-age-bitmap branch 3 times, most recently from f140a43 to 6f0d4fe Compare June 14, 2023 20:39
@eightbitraptor
Copy link
Contributor Author

This is set to 0 for young objects and 1 for old objects, and is used as a performance optimisation for the write barrier. Fetching the age_bits from the heap page and doing the required math to calculate if the object was old or not would slow down the write barrier. So we keep this bit synced in the flags for fast access.

Given that accessing these bits from the heap adds extra performance overhead, can you provide more background as to why these bits are being maintained in a separate location in addition to the flag bits?

@maximecb @byroot @peterzhu2118 and I discussed this outside of Github, but for context I'll summarise here:

We're not maintaining these bits in two separate places. The age of the object is now only being stored in the bitmap attached to a heap page, and the only part of the code that should have to access or modify this bitmap is the age related GC code. This data should be ignored by the rest of the VM.

The FL_PROMOTED bit is being used by the write barrier to decide whether or not it needs to take action for the object.

Currently FL_PROMOTED is being used as a proxy for whether the old object is in the Young or the Old gen, because that's what the write barrier cares about (because of the Old object, Young reference issue); and so superficially, this can be seen as data duplication. We could use the age bits directly from within the write barrier to determine what generation the object is in, but we chose not to do this for a couple of reasons.

  1. Performance - the object is passed into the write barrier function - we don't need to do any extra lookups to check the flags. If we were to look at the age bits, we'd have to find them by calculating where the objects heap page is, and then load them in. This would be much slower.
  2. It would break encapsulation of the GC. The main motivation behind this PR is to get some GC related concerns out of other parts of the VM and back into the GC. Requiring the write barrier to know about age bits, and which ages correspond to which generation would break this encapsulation.

Conceptually, FL_PROMOTED is now just a write barrier trigger, which we could use for any reason if we wanted to trigger a write barrier in the future.

This approach also does not negatively impact performance, as can be seen by the benchmark results on the bug tracker ticket

Copy link
Member

@peterzhu2118 peterzhu2118 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@ioquatix
Copy link
Member

Assuming we go ahead with this, can I humbly request one of the available flag bits for immutability?

@byroot
Copy link
Member

byroot commented Jun 19, 2023

Only one of the two bits is being freed, and we plan to use it to embed T_DATA objects.

@ioquatix
Copy link
Member

ioquatix commented Jun 19, 2023

Okay. Fortunately we are going to be able to free up FL_TAINT. In any case, I've waited for a flag for 2 years for the Immutability PR, which predates Data. I'm interested to know what "embed T_DATA" is, is there a link to the proposal or discussion?

@byroot
Copy link
Member

byroot commented Jun 19, 2023

which predates Data

This has nothing to do with Data.define. And either way I don't think that's what should define what free flags can be used for.

I'm interested to know what "embed T_DATA" is

#7440

@ioquatix
Copy link
Member

This has nothing to do with Data.define. And either way I don't think that's what should define what free flags can be used for.

Of course, but if it comes to it, it should at least be a discussion.

@eightbitraptor eightbitraptor force-pushed the mvh-rvalue-age-bitmap branch 2 times, most recently from b2d7d6f to f05e427 Compare June 23, 2023 19:49
@eightbitraptor eightbitraptor force-pushed the mvh-rvalue-age-bitmap branch from f05e427 to 96ab1ab Compare July 12, 2023 13:04
Closes [Feature #19729]

Previously 2 bits of the flags on each RVALUE are reserved to store the
number of GC cycles that each object has survived. This commit
introduces a new bit array on the heap page, called age_bits, to store
that information instead.

This patch still reserves one of the age bits in the flags (the old
FL_PROMOTED0 bit, now renamed FL_PROMOTED).

This is set to 0 for young objects and 1 for old objects, and is used as
a performance optimisation for the write barrier. Fetching the age_bits
from the heap page and doing the required math to calculate if the
object was old or not would slow down the write barrier. So we keep this
bit synced in the flags for fast access.
@eightbitraptor eightbitraptor force-pushed the mvh-rvalue-age-bitmap branch from 96ab1ab to 203e4d6 Compare July 12, 2023 13:50
@eightbitraptor eightbitraptor merged commit d426343 into ruby:master Jul 13, 2023
@eightbitraptor eightbitraptor deleted the mvh-rvalue-age-bitmap branch July 13, 2023 08:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants