Skip to content

Optimize VM performance with pre-compiled jump table #4010

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

Draft
wants to merge 5 commits into
base: dev
Choose a base branch
from

Conversation

Jim8y
Copy link
Contributor

@Jim8y Jim8y commented Jun 21, 2025

Description

This PR significantly improves Neo VM performance by replacing the reflection-based jump table initialization with a pre-compiled static approach.

Performance Improvements

Benchmark Results:

  • Jump Table Construction: 91μs → 6.8μs (13.3x faster)
  • VM Initialization: 88μs → 0.69μs (127x faster)
  • Overall Performance Gain: 1,235% - 12,613%

Key Changes:

  1. Replaced runtime reflection with compile-time method assignments
  2. Eliminated expensive and calls
  3. Direct opcode-to-method mapping using static initialization

Technical Details

Before (Reflection-based):

foreach (var mi in GetType().GetMethods())
{
    if (Enum.TryParse<OpCode>(mi.Name, true, out var opCode))
    {
        Table[(byte)opCode] = (DelAction)mi.CreateDelegate(typeof(DelAction), this);
    }
}

After (Pre-compiled):

Table[(byte)OpCode.PUSH1] = Push1;
Table[(byte)OpCode.ADD] = Add;
Table[(byte)OpCode.MUL] = Mul;
// ... direct assignments for all opcodes

Testing

  • ✅ All existing unit tests pass (1,599+ tests)
  • ✅ Added comprehensive benchmarks
  • ✅ No breaking changes to public API
  • ✅ Full backward compatibility maintained

Benchmarks

Two benchmark suites included:

    • Full BenchmarkDotNet suite
    • Quick demonstration

Run benchmarks:

NEO_VM_JUMPTABLE_BENCHMARK=1 dotnet run -c Release -f net9.0

Impact

This optimization provides dramatic performance improvements for:

  • Node startup times
  • Smart contract execution initialization
  • High-throughput scenarios with multiple VM instances
  • Development and testing cycles

The changes are particularly beneficial for blockchain nodes that need to create many VM instances for transaction processing.

- Replace reflection-based jump table initialization with static pre-compiled approach
- Achieve 13x faster jump table construction and 127x faster VM initialization
- Add comprehensive benchmarks demonstrating performance improvements
- Maintain full backward compatibility with existing API

Performance improvements:
- Jump table construction: 91μs → 6.8μs (13.3x faster)
- VM initialization: 88μs → 0.69μs (127x faster)
- Reduced memory allocations and better JIT optimization potential

All tests pass and no breaking changes introduced.
@Jim8y Jim8y marked this pull request as draft June 21, 2025 04:31
@Jim8y Jim8y added the DO NOT REVIEW Not yet ready for review, this is just a placeholder pr, will be polished later to make it complete. label Jun 21, 2025
@Wi1l-B0t
Copy link
Contributor

Good job !


Table[(byte)opCode] = (DelAction)mi.CreateDelegate(typeof(DelAction), this);
}
Table[x] = InvalidOpcode;
Copy link
Member

Choose a reason for hiding this comment

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

We can call invalid if it's null

@Wi1l-B0t
Copy link
Contributor

Where ar pre-compiled jump tables saved? Or need to compile every time?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DO NOT REVIEW Not yet ready for review, this is just a placeholder pr, will be polished later to make it complete.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants