Skip to content

ZJIT: Profile type+shape distributions #13901

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

tekknolagi
Copy link
Contributor

@tekknolagi tekknolagi commented Jul 15, 2025

ZJIT uses the interpreter to take type profiles of what objects pass through
the code. It stores a compressed record of the history per opcode for the
opcodes we select.

Before this change, we re-used the HIR Type data-structure, a shallow type
lattice, to store historical type information. This was quick for bringup but
is quite lossy as profiles go: we get one bit per built-in type seen, and if we
see a non-built-in type in addition, we end up with BasicObject. Not very
helpful. Additionally, it does not give us any notion of cardinality: how many
of each type did we see?

This change brings with it a much more interesting slice of type history: a
histogram. A Distribution holds a record of the top-N (where N is fixed at Ruby
compile-time) (Class, ShapeId) pairs and their counts. It also holds an
other count in case we see more than N pairs.

Using this distribution, we can make more informed decisions about when we
should use type information. We can determine if we are strictly monomorphic,
very nearly monomorphic, or something else. Maybe the call-site is polymorphic,
so we should have a polymorphic inline cache. Exciting stuff.

I also plumb this new distribution into the HIR part of the compilation
pipeline.

@tekknolagi tekknolagi force-pushed the mb-shapes-distributions branch 4 times, most recently from 54f34ca to 4a17446 Compare July 18, 2025 17:12
@tekknolagi tekknolagi force-pushed the mb-shapes-distributions branch 3 times, most recently from ec9a182 to 5e9a46e Compare August 1, 2025 16:01
@tekknolagi tekknolagi force-pushed the mb-shapes-distributions branch from 5e9a46e to 9c12d58 Compare August 1, 2025 16:02
@tekknolagi
Copy link
Contributor Author

tekknolagi commented Aug 1, 2025

How can I fix the build so we let these special shape symbols leak? Or should I do something else?

@tekknolagi tekknolagi marked this pull request as ready for review August 1, 2025 16:40
@matzbot matzbot requested a review from a team August 1, 2025 16:40
@k0kubun
Copy link
Member

k0kubun commented Aug 1, 2025

The failure is saying that you published symbols that do not follow our naming convention. It seems like you actually didn't use those symbols from other object files (even cruby_bindings.inc.rs doesn't use them), so you should be able to hide/remove those symbols.

If you want to just use the value of SPECIAL_CONST_SHAPE_ID and INVALID_SHAPE_ID from Rust, you should be able to define them in a way that it doesn't expose those symbols. One way we've done is to define an anonymous enum and refer to them in its variants.

RB_INVALID_SHAPE_ID = INVALID_SHAPE_ID;

bool
rb_zjit_singleton_class_p(VALUE klass)
Copy link
Member

Choose a reason for hiding this comment

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

Until we share them with YJIT, they should be defined in zjit.c. It's confusing to put non-shared things in the shared place, and ZJIT-only implementations should not bloat the YJIT-only binaries.

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ProfiledType {
class: VALUE,
shape: ShapeId,
Copy link
Member

@k0kubun k0kubun Aug 1, 2025

Choose a reason for hiding this comment

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

For non-ivar instructions, is there any plan to use any information other than SPECIAL_CONST_SHAPE_ID?

I feel like immediate: bool (or a set of object flags including that) is what you actually wanted to use. Object shapes in Ruby are basically a cache key to access ivars today, so using all those 32 bits to store the single flag SPECIAL_CONST_SHAPE_ID seems space-inefficient.

For shapes, some instructions would need to query non-class/immediate information, so it might make sense to prepare a storage for instruction-specific profiling data, and store shapes only for ivar instructions.

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.

2 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy