You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
Objecto2 = pop();
Objecto1 = pop();
doubled1 = JRT.toDouble(o1);
doubled2 = JRT.toDouble(o2);
doubleans = 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
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).
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).
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.
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: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/DECsimilarly rebox on every iteration.Possible directions
Longwhere both operands are integral and the result fits — avoidsLong -> Doublechurn and improves output fidelity (relates to the known quirk whereprintf "%s"of an incremented counter prints1.0where gawk prints1).Long.valueOf/a small value cache so common small integers do not allocate (Java caches -128..127 automatically once values staylong).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.jarsrc/jmh/java/io/jawk/backend/AVMExpressionBenchmark.javaalready 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).AwkScriptBenchmarkgives 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