Skip to content

YJIT: Avoid leaks by skipping objects with a singleton class #9693

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
Jan 24, 2024

Conversation

XrXr
Copy link
Member

@XrXr XrXr commented Jan 24, 2024

For receiver with a singleton class, there are multiple vectors YJIT can
end up retaining the object. There is a path in jit_guard_known_klass()
that bakes the receiver into the code, and the object could also be kept
alive indirectly through a path starting at the CME object baked into
the code.

To avoid these leaks, avoid compiling calls on objects with a singleton
class.

See: Shopify#552

There is little to no performance impact on headlining benchmarks:

yjit-pre: ruby 3.4.0dev (2024-01-23T19:00:05Z master 557b69e83b) +YJIT [x86_64-linux]
yjit-post: ruby 3.4.0dev (2024-01-23T23:05:17Z yjit-stop-singleto.. ab19268644) +YJIT [x86_64-linux]

--------------  -------------  ----------  --------------  ----------  -----------------  ------------------
bench           yjit-pre (ms)  stddev (%)  yjit-post (ms)  stddev (%)  yjit-post 1st itr  yjit-pre/yjit-post
activerecord    41.3           1.2         41.0            1.1         1.02               1.01              
chunky-png      627.4          0.5         637.1           0.7         0.99               0.98              
erubi-rails     1397.3         0.4         1439.6          0.4         0.97               0.97              
hexapdf         2112.7         1.9         2117.5          1.3         0.99               1.00              
liquid-c        56.8           1.4         57.1            1.4         1.00               1.00              
liquid-compile  57.3           2.0         57.3            1.5         1.00               1.00              
liquid-render   78.4           1.1         78.7            1.2         1.00               1.00              
lobsters        855.4          1.4         862.8           1.1         1.00               0.99              
mail            120.7          0.8         120.9           0.8         1.00               1.00              
psych-load      1807.1         0.1         1798.4          0.1         1.00               1.00              
railsbench      1726.0         0.3         1735.3          0.3         1.00               0.99              
rubocop         116.6          5.0         116.1           5.2         0.99               1.00              
ruby-lsp        116.8          3.6         114.7           3.5         0.97               1.02              
sequel          66.3           0.8         66.3            0.8         1.00               1.00              
--------------  -------------  ----------  --------------  ----------  -----------------  ------------------

For receiver with a singleton class, there are multiple vectors YJIT can
end up retaining the object. There is a path in jit_guard_known_klass()
that bakes the receiver into the code, and the object could also be kept
alive indirectly through a path starting at the CME object baked into
the code.

To avoid these leaks, avoid compiling calls on objects with a singleton
class.

See: Shopify#552
@matzbot matzbot requested a review from a team January 24, 2024 20:59
@XrXr XrXr merged commit 2cc7a56 into ruby:master Jan 24, 2024
@XrXr XrXr deleted the yjit-stop-singleton-classes branch January 24, 2024 23:06
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.

None yet

3 participants