solidity icon indicating copy to clipboard operation
solidity copied to clipboard

perf: evmasm hasInstruction called unnecessarily

Open DaniPopes opened this issue 3 weeks ago • 0 comments

evmasm::AssemblyItem::operator== is pretty hot, especially in the peephole optimizer:

https://github.com/argotorg/solidity/blob/08c4e0c6cfab9d6f303fefbf0ad081e06fa4a532/libevmasm/AssemblyItem.h#L248-L252

This operator calls hasInstruction() twice, once in the actual operator, and the second time in the instruction() solAssert: https://github.com/argotorg/solidity/blob/08c4e0c6cfab9d6f303fefbf0ad081e06fa4a532/libevmasm/AssemblyItem.h#L218

This is enough to show up in profiles. The solAssert should either be a debug-only assert, or operator== should not repeat the check by using m_instruction directly. I would prefer the former since operator== is not the only hot callsite for hasInstruction().

This function (instruction() calling hasInstruction()) is BY FAR the most time consuming operation in the evmasm optimizer.

This should be a single line change for an estimated E2E 5-10% performance improvement in optimized compilations.


On solady:

~/github/solady main !1 ?3 ❯ hyperfine -w1 --prepare 'forge clean' 'SOLC=solcd forge b' 'SOLC=solcd2 forge b'        ✘ INT 18:34:21
Benchmark 1: SOLC=solcd forge b
  Time (mean ± σ):     18.934 s ±  0.425 s    [User: 17.609 s, System: 0.865 s]
  Range (min … max):   18.657 s … 19.703 s    10 runs

  Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs.

Benchmark 2: SOLC=solcd2 forge b
  Time (mean ± σ):     17.796 s ±  0.332 s    [User: 16.329 s, System: 0.834 s]
  Range (min … max):   17.639 s … 18.735 s    10 runs

  Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs.

Summary
  SOLC=solcd2 forge b ran
    1.06 ± 0.03 times faster than SOLC=solcd forge b

this is using a custom script as solc that uses the binary in the SOLC env var. this is the same as '--use X' in forge but i was using it for other profiling.

version 0.8.31-develop.2025.11.19+commit.08c4e0c6.mod.Darwin.appleclang (08c4e0c6cfab9d6f303fefbf0ad081e06fa4a532)

the diff for solcd and solcd2 is:

diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h
index dcb4bf3a7..59ebb7e15 100644
--- a/libevmasm/AssemblyItem.h
+++ b/libevmasm/AssemblyItem.h
@@ -215,7 +215,7 @@ public:
        /// @returns the instruction of this item (only valid if hasInstruction returns true)
        Instruction instruction() const
        {
-               solAssert(hasInstruction());
+               // solAssert(hasInstruction());
                return *m_instruction;
        }

DaniPopes avatar Nov 19 '25 19:11 DaniPopes