Skip to content

Performance: replace the boxed ArrayDeque operand stack with a flat Object[] stack #536

Description

@bertysentry

Motivation

The AVM interpreter is ~4.4x slower than gawk on a tight arithmetic loop (measured on the PR #534 branch, but this is long-standing and unrelated to runtime typing):

BEGIN { s=0; for(i=0;i<5000000;i++) s=s+i; print s }
  • gawk: ~1.5 s
  • jawk: ~6.5 s

Problem

Every opcode pushes/pops operands through Deque<Object> operandStack = new ArrayDeque<Object>() (AVM.java). Each access pays:

  • ArrayDeque.push/pop call overhead: internal head-index wraparound math, capacity checks, and null checks
  • a NULL_OPERAND sentinel mapping on both push() and pop() (AVM.pop()/AVM.push())

A typical statement like s = s + i executes 4-6 opcodes, each with 1-2 stack operations, so this overhead multiplies across every executed tuple.

Proposal

Replace the deque with a plain Object[] and an explicit top-of-stack index owned by the AVM:

  • push/pop/peek become single array accesses that the JIT can fully inline
  • grow the array on demand (operand stack depth is bounded by expression nesting, so it stays small)
  • the NULL_OPERAND sentinel can likely be dropped since the AVM controls all accesses and can allow null slots directly

The operand stack is fully encapsulated behind push()/pop() in AVM (with a couple of operandStack.clear() call sites), so this is a contained change.

Note

popArguments() and print/printf argument gathering also allocate an Object[] per call; worth revisiting in the same pass where they sit on hot paths.

Measurement

Use the project's existing JMH harness rather than wall-clock CLI timings:

mvn package -Pbenchmark -DskipTests
java -jar target/jawk-*-benchmarks.jar

src/jmh/java/io/jawk/backend/AVMExpressionBenchmark.java already exercises the interpreter's expression evaluation and is the right place to anchor before/after numbers (add a tight arithmetic-loop case there if not already covered). AwkScriptBenchmark gives the end-to-end view. The gawk-vs-jawk CLI numbers above are motivation only — JMH results are the acceptance criterion.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions