Skip to content

Performance: reduce boxing churn in arithmetic and comparison hot paths #537

Description

@bertysentry

Motivation

Same baseline as #536: jawk is ~4.4x slower than gawk on BEGIN { s=0; for(i=0;i<5000000;i++) s=s+i; print s } (~6.5 s vs ~1.5 s). Beyond the operand stack itself (#536), the arithmetic opcodes allocate on every operation.

Problem

Each binary arithmetic opcode (ADD, SUBTRACT, MULTIPLY, ...) does:

Object o2 = pop();
Object o1 = pop();
double d1 = JRT.toDouble(o1);
double d2 = JRT.toDouble(o2);
double ans = d1 + d2;
push(ans);   // autoboxes a new Double on every single operation

So a 5M-iteration loop allocates at minimum 10M+ boxed Doubles (the add, the increment, the comparison result), plus the garbage-collection pressure that goes with it. INC/DEC similarly rebox on every iteration.

Possible directions

  1. Keep exact integral results as Long where both operands are integral and the result fits — avoids Long -> Double churn and improves output fidelity (relates to the known quirk where printf "%s" of an incremented counter prints 1.0 where gawk prints 1).
  2. Box cache: route results through Long.valueOf/a small value cache so common small integers do not allocate (Java caches -128..127 automatically once values stay long).
  3. Longer term: a tagged accumulator or dual-stack design (separate double stack) so arithmetic chains stay unboxed between variable loads and stores. Larger change; only worth it after 1-2 and Performance: replace the boxed ArrayDeque operand stack with a flat Object[] stack #536 are measured.

Benchmarks should be re-run after #536, since the two overheads overlap on the same opcodes.

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