Skip to content

Optimizing VM - #575

Merged
shargon merged 30 commits into
neo-project:masterfrom
Turalchik:optimize-vm
Jul 7, 2026
Merged

shargon merged 30 commits into
neo-project:masterfrom
Turalchik:optimize-vm

Conversation

@Turalchik

Copy link
Copy Markdown
Contributor

This pull request brings the asymptotic complexity of the opcodes closer to https://github.com/nspcc-dev/neo-go. Basically, this PR presents refcounting optimizations in opcodes, in which items are removed from the stack, which shortly after that will be there on the stack.

Tural Devrishev added 10 commits May 5, 2026 12:01
Signed-off-by: Tural Devrishev <tural@nspcc.ru>
Signed-off-by: Tural Devrishev <tural@nspcc.ru>
Signed-off-by: Tural Devrishev <tural@nspcc.ru>
Signed-off-by: Tural Devrishev <tural@nspcc.ru>
Signed-off-by: Tural Devrishev <tural@nspcc.ru>
Signed-off-by: Tural Devrishev <tural@nspcc.ru>
Signed-off-by: Tural Devrishev <tural@nspcc.ru>
Signed-off-by: Tural Devrishev <tural@nspcc.ru>
Signed-off-by: Tural Devrishev <tural@nspcc.ru>
Signed-off-by: Tural Devrishev <tural@nspcc.ru>
@codecov

codecov Bot commented May 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.04651% with 24 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.47%. Comparing base (348476f) to head (5ab6f21).

Files with missing lines Patch % Lines
src/Neo.VM/JumpTable/JumpTable.Compound.cs 79.27% 19 Missing and 4 partials ⚠️
src/Neo.VM/Slot.cs 94.44% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #575      +/-   ##
==========================================
- Coverage   85.61%   85.47%   -0.14%     
==========================================
  Files          41       41              
  Lines        2606     2720     +114     
  Branches      338      345       +7     
==========================================
+ Hits         2231     2325      +94     
- Misses        287      304      +17     
- Partials       88       91       +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread src/Neo.VM/JumpTable/JumpTable.Compound.cs
Signed-off-by: Tural Devrishev <tural@nspcc.ru>
@Turalchik
Turalchik requested a review from shargon May 13, 2026 09:38
Signed-off-by: Tural Devrishev <tural@nspcc.ru>

@Jim8y Jim8y left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

SETITEM now removes the new value with PopNoRef() before validating the array index. If the array branch then throws the catchable out-of-range exception, the value has already been removed from the evaluation stack but its stack reference is never removed. A script can catch that exception and continue with an inflated ReferenceCounter.Count, which can later trigger incorrect MaxStackSize failures.\n\nI reproduced this with a TRY/CATCH around an out-of-range array SETITEM: the same test passes on base with count 0 after the catch, but this PR leaves count 1. Please either keep the normal Pop() until all catchable validation is complete, or remove the value reference on every failure path before rethrowing.

@shargon shargon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's better to use internal because these calls can desynchronize the reference counter

Comment thread src/Neo.VM/ExecutionEngine.cs Outdated
Comment thread src/Neo.VM/ExecutionEngine.cs Outdated
Comment thread src/Neo.VM/ExecutionEngine.cs Outdated
Tural Devrishev added 2 commits May 14, 2026 11:29
Signed-off-by: Tural Devrishev <tural@nspcc.ru>
Signed-off-by: Tural Devrishev <tural@nspcc.ru>
@Turalchik
Turalchik requested review from Jim8y and shargon May 14, 2026 08:33

@Jim8y Jim8y left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for updating the reference-counter helpers to internal and fixing the array out-of-range path. I found one remaining blocker in the Buffer SETITEM branch: the value is removed before validating the buffer index, then removed again on the out-of-range catchable path. A handled script such as TRY; PUSH1; NEWBUFFER; PUSH2; PUSH0; SETITEM; DROP; ENDTRY halts with ReferenceCounter.Count == -1 instead of 0. I reproduced it by adding a focused UT_ReferenceCounter test and running dotnet test tests/Neo.VM.Tests/Neo.VM.Tests.csproj --filter TestSetItemBufferCatchableIndexFailureBalancesReferences --verbosity minimal.

Signed-off-by: Tural Devrishev <tural@nspcc.ru>
Jim8y
Jim8y previously approved these changes May 16, 2026

@Jim8y Jim8y left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Rechecked the latest head. The Buffer SETITEM catchable out-of-range path now keeps the reference counter balanced, and the new JSON case covers it. I also ran Determining projects to restore...
All projects are up-to-date for restore.
Neo.VM -> /private/tmp/neo-vm-review-575/src/Neo.VM/bin/Debug/net10.0/Neo.VM.dll
Neo.VM.Tests -> /private/tmp/neo-vm-review-575/tests/Neo.VM.Tests/bin/Debug/net10.0/Neo.VM.Tests.dll
Test run for /private/tmp/neo-vm-review-575/tests/Neo.VM.Tests/bin/Debug/net10.0/Neo.VM.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.

Passed! - Failed: 0, Passed: 156, Skipped: 0, Total: 156, Duration: 647 ms - Neo.VM.Tests.dll (net10.0) successfully.

@Turalchik

Turalchik commented May 18, 2026

Copy link
Copy Markdown
Contributor Author

On neo-project/neo#4546 there was a question about optimizing the ROT opcode, I executed benchmarks for this opcode from this file https://github.com/neo-project/neo-vm/blob/ed0eb66359fd1d76ddb5be91cc5a703ddc714a18/benchmarks/Neo.VM.Benchmarks/OpCodes/Benchmarks_StackOps.cs and I got the following results

Old ROT with two swap:

Method Mean Error StdDev Median Gen0 Gen1 Gen2 Allocated
ROT_Shallow_3x1000 293.0 us 9.73 us 25.65 us 286.9 us - - - 139.64 KB
ROT_Deep_100x1000 305.2 us 6.08 us 11.87 us 303.0 us - - - 152.3 KB
ROT_Multiple_50x1000 9,214.9 us 614.24 us 1,732.46 us 8,450.0 us 1000.0000 1000.0000 1000.0000 5931.26 KB

New ROT using roll:

Method Mean Error StdDev Gen0 Gen1 Gen2 Allocated
ROT_Shallow_3x1000 259.9 us 5.14 us 7.04 us - - - 139.64 KB
ROT_Deep_100x1000 295.7 us 5.87 us 12.00 us - - - 152.3 KB
ROT_Multiple_50x1000 8,342.5 us 279.26 us 764.47 us 1000.0000 1000.0000 1000.0000 5931.26 KB

Comment thread src/Neo.VM/EvaluationStack.cs Outdated
Signed-off-by: Tural Devrishev <tural@nspcc.ru>
shargon and others added 3 commits June 8, 2026 20:30
Use these helpers instead of adding/removal virtual Null stackitems for
more eplicity. No functional changes.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>

@AnnaShaleva AnnaShaleva left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. The code is compatible with NeoGo. Let's merge this PR firstly, it contains optimisations only, and then we'll rebase the #571 onto fresh master.

@neo-project/core please, review.

@ajara87 ajara87 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm

@superboyiii

Copy link
Copy Markdown
Member

I'm testing data compatibility...

@superboyiii superboyiii left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@AnnaShaleva @Turalchik Data is compatible.

@shargon shargon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@AnnaShaleva is this required for 3.10.1?

@AnnaShaleva

Copy link
Copy Markdown
Member

is this required for 3.10.1?

Not strictly required. But I'd suggest to include it to v3.10.1 to proceed with dynamic opcodes step-by step. This PR doesn't contain any incompatible changes.

Comment thread src/Neo.VM/JumpTable/JumpTable.Compound.cs
@superboyiii

superboyiii commented Jul 6, 2026

Copy link
Copy Markdown
Member

Merge? Then we can begin to release vm.

@AnnaShaleva

Copy link
Copy Markdown
Member

Merge? Then we can begin to release vm.

Yes.

@ajara87

ajara87 commented Jul 6, 2026

Copy link
Copy Markdown
Member

@shargon could you merge?

@shargon

shargon commented Jul 6, 2026

Copy link
Copy Markdown
Member

In my opinion this should wait to next release, it's not critical and it's related to dynamic prices

@vncoelho

vncoelho commented Jul 6, 2026

Copy link
Copy Markdown
Member

I believe this PR should be merged for N4 only, and battle tested for 3.11.0 together with dynamic opcodes price

@superboyiii

Copy link
Copy Markdown
Member

VM v3.10.1 is released, it's good to merge now.

@shargon
shargon merged commit 99095c2 into neo-project:master Jul 7, 2026
5 checks passed
roman-khimov added a commit to nspcc-dev/neo-go that referenced this pull request Jul 23, 2026
C# VM <= 3.10.1 checks the parameter first and then looks into the stack
(checking its length), this means that ROLL(0) is effectively NOP in that it
can work even with empty stack. C# master (with neo-project/neo-vm#575)
is the same as NeoGo, so we have no reason to change the behavior as well.
Add a test similar to neo-project/neo-vm#589.

Reported-by: Majid Mohammed <majidcoderlun3x@gmail.com>
Signed-off-by: Roman Khimov <roman@nspcc.ru>
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.

7 participants