Skip to content

Comments

Eliminate all Core.Box captures to reduce latency and allocations#5475

Open
hz-xiaxz wants to merge 86 commits intoMakieOrg:masterfrom
hz-xiaxz:feature/avoid-boxes-optimizations
Open

Eliminate all Core.Box captures to reduce latency and allocations#5475
hz-xiaxz wants to merge 86 commits intoMakieOrg:masterfrom
hz-xiaxz:feature/avoid-boxes-optimizations

Conversation

@hz-xiaxz
Copy link

@hz-xiaxz hz-xiaxz commented Jan 1, 2026

Description

This PR addresses a significant number of Core.Box captures throughout the codebase. These were identified using the scanning script from JuliaLang/julia#60478.
Core.Box occurs when the compiler cannot infer the type or lifetime of a variable captured in a closure (often due to reassignment), forcing it onto the heap. This causes:
Type instabilities (inhibiting optimizations like SIMD).
Unnecessary allocations (increasing GC pressure).
Latency (compilation overhead).
While this PR touches many files, the changes are largely mechanical. I hope it won't be a large burden to review.

Strategies Used

To eliminate boxing, I employed several standard techniques depending on the context:

  1. SSA-style Renaming: Ensuring variables captured by closures are not reassigned (e.g., x = ...; x = ... changed to x_init = ...; x_final = ...).
  2. Ref containers: Using Ref for variables that genuinely need to be mutated inside closures (e.g., buffers or counters), keeping the binding constant.
  3. Explicit Loops: Replacing map with explicit for loops where stateful iteration made closures inefficient.
  4. Lifting Functions: Moving named inner functions to the module scope where they don't capture local variables.
  5. Ordering: Fixing forward-reference issues by declaring variables before their capturing closures.

The scan results show a drastic reduction in boxed variables.

Before (Detected Boxes)
Var Func Location
pvmf32 #553 projection_utils.jl:276
viewport #Scene#303 scenes.jl:236
labels #get_labeled_plots legend.jl:1014
lplots #get_labeled_plots legend.jl:1014
pos #initialize_block! textbox.jl:162
relayout #initialize_block! legend.jl:42
i #initialize_block! menu.jl:1
was_inside_button #initialize_block! menu.jl:1
was_inside_options #initialize_block! menu.jl:1
last_task #on_latest observables.jl:26
run_f #on_latest observables.jl:26
N #plot! contours.jl:180
mesh_idx #plot! poly.jl:183
xy #position_on_plot ray_casting.jl:378
nrows #print_columns recipes.jl:709
new_theme #set_theme! theming.jl:209
ticklabels LineAxis lineaxis.jl:264
fn String text.jl:874
result_type _register_argument_conversions! compute-plots.jl:491
x _register_argument_conversions! compute-plots.jl:491
align add_ticks_and_ticklabels! axis3d.jl:592
maxi aggregation_implementation! datashader.jl:143
mini aggregation_implementation! datashader.jl:143
i attribute_per_char text_layouting.jl:9
bar_labels barplot_labels barplot.jl:262
deregister connect_conversions! dim-converts.jl:121
tfontsize draw_axis3d axis.jl:226
cam initialize_block! axis3d.jl:3
default_format initialize_block! slidergrid.jl:8
extract_range_format initialize_block! slidergrid.jl:8
reset_to_stored initialize_block! textbox.jl:4
textplot initialize_block! textbox.jl:4
x1 line_rectangle_intersection annotation.jl:920
x2 line_rectangle_intersection annotation.jl:920
y1 line_rectangle_intersection annotation.jl:920
y2 line_rectangle_intersection annotation.jl:920
deregister needs_tick_update_observable dim-converts.jl:160
lastcomm parse_bezier_commands bezier.jl:401
buffer plot! timeseries.jl:39
nanpoint plot! band.jl:36
h projectionmatrix axis3d.jl:331
w projectionmatrix axis3d.jl:331
field replay_events event-recorder.jl:32
value replay_events event-recorder.jl:32
ind streamplot_impl streamplot.jl:134
c1 to_image patterns.jl:126
c2 to_image patterns.jl:126
bb unchecked_boundingbox text_boundingbox.jl:28
update_plotlist update_plotspecs! specapi.jl:666
color voxel_colors voxels.jl:282

After: No

We can add a Test.detect_closure_boxes in tests to avoid introducing more boxes.

Type of change

Delete options that do not apply:

  • Performance?

AI Disclose

I used some AI to assist me, but checked manually.

Checklist

  • Added an entry in CHANGELOG.md (for new features and breaking changes)
  • Added or changed relevant sections in the documentation
  • Added unit tests for new algorithms, conversion methods, etc.
  • Added reference image tests for new plotting functions, recipes, visual options, etc.

USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU  WHAT
hzxiaxz  pts/1    -                13:53    1:29m  0.45s  0.45s -zsh,  variables to avoid boxing
@hz-xiaxz
Copy link
Author

Motivated by the performance bump, I continued to eliminate all Core.Box found by JETLS.

@hz-xiaxz hz-xiaxz changed the title Eliminate many Core.Box captures to reduce latency and allocations Eliminate all Core.Box captures to reduce latency and allocations Feb 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changelog Skips changelog enforcer

Projects

Status: Ready to merge

Development

Successfully merging this pull request may close these issues.

2 participants