Skip to content

Marshal load perf#9365

Merged
headius merged 4 commits intojruby:masterfrom
headius:marshal_load_perf
Apr 14, 2026
Merged

Marshal load perf#9365
headius merged 4 commits intojruby:masterfrom
headius:marshal_load_perf

Conversation

@headius
Copy link
Copy Markdown
Member

@headius headius commented Apr 6, 2026

Several performance improvements for Marshal.load based on the benchmark and results in #9136:

  • Don't perform link handling for values that don't link, like low integers.
  • Avoid constructing the partials map when no proc was given.
  • Simplify post-load object-freezing logic.
  • Avoid allocating symbol and object links collections until needed.

@headius headius added this to the JRuby 10.1.0.0 milestone Apr 6, 2026
headius added 4 commits April 5, 2026 20:48
Fixnums, true, false, and nil cannot be partially unmarshaled and
are never registered with the partial map, but the previous code
still attempted to remove them from that map. Likely due to
overhead from acquiring and installing an identity hash code in
RubyFixnum objects, this appears to have significantly degraded
Marshal.load performance for large numbers of int-ranged Integer
objects as reported in jruby#9136.

The change here removes the "leave" logic from the marshal load
logic for core types which cannot be partial and which do not get
registered with the partial map via an "entry" call. This improves
performance of the reported benchmark back to JRuby 1.7.27 levels.
The partials map is only used to avoid invoking the caller's proc
with a partially-initialized object, such as one that is still
loading instance variables. If no proc was given, partially-
initialized objects will never be visible, so there's no reason to
track them. This commit eliminates the use of the partials map
completely in that case.

This alone would be sufficient to fix jruby#9136, but
previous commits also removed the partials usage for core types
that do not get registered in it.

The change here dramatically improves the performance of loading
nearly all types of values in bench/bench_marshal_load.rb and also
reduces allocation by eliminating the partials map when unused.
Many uses of Marshal will not encounter the same objects in the
stream, so don't allocate these link-tracking collections until
needed.
@headius headius force-pushed the marshal_load_perf branch from 9ba8960 to e5f5c51 Compare April 6, 2026 01:48
@headius headius merged commit ba3d3ef into jruby:master Apr 14, 2026
107 checks passed
@headius headius deleted the marshal_load_perf branch April 14, 2026 19:35
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.

1 participant