Skip to content

Speed up variable access with SIMD scan and slot inline caches#191

Merged
hadashiA merged 3 commits into
mainfrom
claude/symbol-performance-fa1178
Jul 13, 2026
Merged

Speed up variable access with SIMD scan and slot inline caches#191
hadashiA merged 3 commits into
mainfrom
claude/symbol-performance-fa1178

Conversation

@hadashiA

Copy link
Copy Markdown
Owner

Summary

Two layered optimizations for Symbol-keyed variable lookup in the interpreter, worth +26% on optcarrot combined (18.9 → 23.8–24.0 fps, video checksum unchanged).

1. SIMD scan for VariableTable

Symbol is a single uint, so the key array can be searched with the vectorized MemoryExtensions.IndexOf over MemoryMarshal.Cast<Symbol, uint> instead of a scalar loop. optcarrot's PPU has 79 distinct ivars (CPU: 36), so the linear scan was a real cost: this alone is +10% on optcarrot.

2. Slot inline caches for variable-access opcodes

Irep.VariableSlotCache stores a ushort slot guess per symbol-pool index, used by GetIV/SetIV/GetGV/SetGV and the GetConst fast path; the trivial-getter fast path in Send gets the same treatment via MethodCacheEntry.TrivialGetterSlot.

Cached slots are verified guesses: every use re-checks keys[slot] == symbol (TryGetAt/TrySetAt), so stale slots (after remove_instance_variable, table growth, or a call site alternating between different layouts) can never read or write the wrong variable — they just fall back to the scan and re-learn the slot.

Miss paths are deliberately [MethodImpl(NoInlining)]: an earlier version with the miss path inlined into the dispatch-switch case bodies lost the entire SIMD win on optcarrot due to code-layout effects, despite winning on a microbenchmark.

Numbers

benchmark base SIMD only SIMD + IC
optcarrot 18.5–19.1 fps 21.5–21.7 23.7–24.0
bm_ao_render ~2900 ms neutral −5% ~ neutral
bm_ivar (60 ivars) ~112 ms ~58 ~37 (3.0x)

Interleaved runs, alternating order, compared within round; optcarrot checksum 59662 identical in every configuration.

Tests

  • New tests/ChibiRuby.Tests/ruby/test/variables.rb: slot shift after remove_instance_variable, one call site alternating between different ivar layouts, reads through a warmed site on an empty table, global table growth mid-loop.
  • Full suite: 155 passed. All TFMs (net8.0/9.0/10.0 + netstandard2.1) build.

Also adds a --quick-script <file.rb> [iters] [warmups] wall-clock runner and ruby/bm_ivar.rb to ChibiRuby.Benchmark.

🤖 Generated with Claude Code

…ance-fa1178

# Conflicts:
#	src/ChibiRuby/MRubyState.Vm.cs
@hadashiA hadashiA merged commit 9308fe2 into main Jul 13, 2026
1 check passed
@hadashiA hadashiA deleted the claude/symbol-performance-fa1178 branch July 13, 2026 09: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.

1 participant