perf(core): promote per region, promote BEGIN loops, keep loops off the memory stack
Promotion was all-or-nothing per word, so one `.` or one host call put the whole body -- hot loops included -- on the memory data stack, where a loop-carried add costs 2.2 ns/iteration instead of 0.31. The stack simulator now runs over each promotable stretch of a word; BEGIN/UNTIL, BEGIN/AGAIN and BEGIN/WHILE/REPEAT join DO/LOOP as promotable when the construct is provably stack-neutral; and the inliner no longer moves a loop-bearing callee into a caller that can never be promoted. Fixes a bug the BEGIN work uncovered, present since promotion was introduced and shipped in 0.2.6: the loop fixup and the IF join copied locals one slot at a time in index order, so a body that permutes the stack lost a value -- `: C 3 4 2 0 DO SWAP LOOP . . ;` printed `4 4` where gforth prints `4 3`. Four of five benchmarks now beat sf64: Factorial 0.29x, Collatz 0.30x, NestedLoops 0.27x, GCD 0.67x. Only Fibonacci is behind, at 1.24x. Also scale GCD, Factorial and NestedLoops, which ran in 14-51 us where scatter and fixed costs dominated -- that is what exposed GCD as a loss and pointed at BEGIN. WS-014, WS-015, WS-016, WS-019.
This commit is contained in:
@@ -746,37 +746,37 @@ fn perf_benchmarks() -> Vec<PerfBenchmark> {
|
||||
verify: "25 FIB",
|
||||
expected: 75025,
|
||||
samples: 5,
|
||||
max_ratio: 0.65,
|
||||
max_ratio: 0.17,
|
||||
},
|
||||
PerfBenchmark {
|
||||
name: "Factorial(12)x10K",
|
||||
name: "Factorial(12)x100K",
|
||||
define: ": FACT 1 SWAP 1+ 1 ?DO I * LOOP ; \
|
||||
: FACT-BENCH 10000 0 DO 12 FACT DROP LOOP ;",
|
||||
: FACT-BENCH 100000 0 DO 12 FACT DROP LOOP ;",
|
||||
run_code: "FACT-BENCH",
|
||||
verify: "12 FACT",
|
||||
expected: 479001600,
|
||||
samples: 5,
|
||||
max_ratio: 0.75,
|
||||
max_ratio: 0.12,
|
||||
},
|
||||
PerfBenchmark {
|
||||
name: "GCD-bench(500)",
|
||||
name: "GCD-bench(20K)",
|
||||
define: ": GCD BEGIN DUP WHILE TUCK MOD REPEAT DROP ; \
|
||||
: GCD-BENCH 0 DO 10000 I 1+ GCD DROP LOOP ;",
|
||||
run_code: "500 GCD-BENCH",
|
||||
run_code: "20000 GCD-BENCH",
|
||||
verify: "48 36 GCD",
|
||||
expected: 12,
|
||||
samples: 5,
|
||||
max_ratio: 0.70,
|
||||
max_ratio: 0.45,
|
||||
},
|
||||
PerfBenchmark {
|
||||
name: "NestedLoops(50)",
|
||||
name: "NestedLoops(50)x1K",
|
||||
define: ": NESTED 0 SWAP 0 DO I 0 ?DO I J + DROP LOOP LOOP ; \
|
||||
: NESTED-BENCH 100 0 DO 50 NESTED DROP LOOP ;",
|
||||
: NESTED-BENCH 1000 0 DO 50 NESTED DROP LOOP ;",
|
||||
run_code: "NESTED-BENCH",
|
||||
verify: "5 NESTED",
|
||||
expected: 0,
|
||||
samples: 3,
|
||||
max_ratio: 0.20,
|
||||
samples: 5,
|
||||
max_ratio: 0.11,
|
||||
},
|
||||
PerfBenchmark {
|
||||
name: "Collatz(2K)",
|
||||
@@ -788,7 +788,7 @@ fn perf_benchmarks() -> Vec<PerfBenchmark> {
|
||||
verify: "27 COLLATZ",
|
||||
expected: 111,
|
||||
samples: 3,
|
||||
max_ratio: 0.45,
|
||||
max_ratio: 0.08,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user