Open
Description
The integer/Char pattern matching optimization output is worse than that of the plain switch table.
For this example
benchmark.mjs
import { bench, run, barplot, summary, do_not_optimize } from "mitata";
import fc from "fast-check";
const samples = fc.sample(
fc.integer({ min: 0, max: 256 }),
{ numRuns: 10000, seed: 42 }
);
function isFinalIf(ch) {
return (
ch === 48
|| ch === 49
|| ch === 50
|| ch === 51
|| ch === 52
|| ch === 53
|| ch === 54
|| ch === 55
|| ch === 56
|| ch === 57
|| ch === 65
|| ch === 66
|| ch === 67
|| ch === 68
|| ch === 69
|| ch === 70
|| ch === 71
|| ch === 72
|| ch === 73
|| ch === 74
|| ch === 75
|| ch === 76
|| ch === 77
|| ch === 78
|| ch === 79
|| ch === 80
|| ch === 82
|| ch === 83
|| ch === 84
|| ch === 85
|| ch === 86
|| ch === 87
|| ch === 88
|| ch === 89
|| ch === 90
|| ch === 97
|| ch === 99
|| ch === 102
|| ch === 110
|| ch === 113
|| ch === 117
|| ch === 121
|| ch === 61
|| ch === 60
|| ch === 62
|| ch === 126
);
}
function isFinalSwitch(ch) {
switch (ch) {
case 48:
case 49:
case 50:
case 51:
case 52:
case 53:
case 54:
case 55:
case 56:
case 57:
case 65:
case 66:
case 67:
case 68:
case 69:
case 70:
case 71:
case 72:
case 73:
case 74:
case 75:
case 76:
case 77:
case 78:
case 79:
case 80:
case 82:
case 83:
case 84:
case 85:
case 86:
case 87:
case 88:
case 89:
case 90:
case 97:
case 99:
case 102:
case 110:
case 113:
case 117:
case 121:
case 61:
case 60:
case 62:
case 126:
return true;
}
return false;
}
function isFinalIncludes(ch) {
return [
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77,
78,
79,
80,
82,
83,
84,
85,
86,
87,
88,
89,
90,
97,
99,
102,
110,
113,
117,
121,
61,
60,
62,
126,
].includes(ch);
}
/** Generated by ReScript v12.0.0-alpha.13
*
* [Open in Playground](https://rescript-lang.org/try?version=v12.0.0-alpha.13&module=esmodule&code=DYUwLgBAlgzgYlAdgQ2ASUZAvBAxgCwiwD4IBvAKAghgHcowC9DLqAfCAFgA4qIPOATj4cArAAYREUQEYpogEzyAzPM7zR8gGzyA7FK2b2ELTuNb953ueHHdku3LtK7qu+rtH+EXWe+7Lf2t-W29uBzCXMLcwjzCvDm4-RMDE4MTQjkEIrNSIQUyIGXEojhliqXKYspk8mQUnby1Gji0ck1KihS0iUjAAJwBXECkAfV6IADNUGBHqAF8KRaA)
*/
function isFinalRes(ch) {
if (ch < 63) {
if (ch >= 58) {
return ch >= 60;
} else {
return ch >= 48;
}
}
if (ch < 81) {
return ch >= 65;
}
if (ch >= 127) {
return false;
}
switch (ch) {
case 81:
case 91:
case 92:
case 93:
case 94:
case 95:
case 96:
case 98:
case 100:
case 101:
case 103:
case 104:
case 105:
case 106:
case 107:
case 108:
case 109:
case 111:
case 112:
case 114:
case 115:
case 116:
case 118:
case 119:
case 120:
case 122:
case 123:
case 124:
case 125:
return false;
case 82:
case 83:
case 84:
case 85:
case 86:
case 87:
case 88:
case 89:
case 90:
case 97:
case 99:
case 102:
case 110:
case 113:
case 117:
case 121:
case 126:
return true;
}
return false;
}
summary(() => {
barplot(() => {
bench("if-else chain", () => {
do_not_optimize(samples.filter(isFinalIf));
});
bench("switch statement", () => {
do_not_optimize(samples.filter(isFinalSwitch));
});
bench("array includes", () => {
do_not_optimize(samples.filter(isFinalIncludes));
});
bench("ReScript pattern", () => {
do_not_optimize(samples.filter(isFinalRes));
}).baseline();
});
});
run();
And gives the following results on my machine:
$ node --expose-gc benchmark.mjs
clk: ~4.48 GHz
cpu: Intel(R) Core(TM) Ultra 7 258V
runtime: node 24.0.2 (x64-linux)
...
ReScript pattern
1.75x slower than switch statement
1.24x faster than if-else chain
2.49x faster than array includes
$ bun --expose-gc benchmark.mjs
clk: ~4.49 GHz
cpu: Intel(R) Core(TM) Ultra 7 258V
runtime: bun 1.2.13 (x64-linux)
...
summary
ReScript pattern
2.22x slower than switch statement
2.03x faster than array includes
3.33x faster than if-else chain
According to this micro benchmark, the branches generated by ReScript are never faster than the simplest naive switch case.
Metadata
Metadata
Assignees
Labels
No labels