1pub struct CoreBenchCase {
2 pub slug: &'static str,
3 pub name: &'static str,
4 pub source: &'static str,
5}
6
7impl CoreBenchCase {
8 pub fn module_root(&self) -> Option<&'static str> {
9 match self.slug {
10 "json_roundtrip_1k" => Some("examples"),
11 _ => None,
12 }
13 }
14
15 pub fn source_is_module(&self) -> bool {
16 self.source.trim_start().starts_with("module ")
17 }
18}
19
20const FIBONACCI: &str = "\
21fn fib(n: Int) -> Int
22 match n < 2
23 true -> n
24 false -> fib(n - 1) + fib(n - 2)
25
26fn main() -> Int
27 fib(25)
28";
29
30const SUM_TCO: &str = "\
31fn sum(n: Int, acc: Int) -> Int
32 match n == 0
33 true -> acc
34 false -> sum(n - 1, acc + n)
35
36fn main() -> Int
37 sum(10000000, 0)
38";
39
40const COUNTDOWN: &str = "\
41fn countdown(n: Int) -> Int
42 match n == 0
43 true -> 0
44 false -> countdown(n - 1)
45
46fn main() -> Int
47 countdown(10000000)
48";
49
50const FACTORIAL_TCO: &str = "\
51fn fact(n: Int, acc: Int) -> Int
52 match n == 0
53 true -> acc
54 false -> fact(n - 1, acc * n)
55
56fn repeat(n: Int, acc: Int) -> Int
57 match n == 0
58 true -> acc
59 false -> repeat(n - 1, acc + Result.withDefault(Int.mod(fact(20, 1), 1000000), 0))
60
61fn main() -> Int
62 repeat(50000, 0)
63";
64
65const NESTED_MATCH: &str = "\
66fn abs(n: Int) -> Int\n match n < 0\n true -> 0 - n\n false -> n\n\nfn classify(n: Int) -> Int\n match n == 0\n true -> 0\n false -> abs(n) * 2\n\nfn run(n: Int, acc: Int) -> Int\n match n == 0\n true -> acc\n false -> run(n - 1, acc + classify(n - 180000))\n\nfn main() -> Int\n run(360000, 0)\n";
67
68const RESULT_CHAIN: &str = "\
69fn safeDivide(a: Int, b: Int) -> Result<Int, Int>\n match b == 0\n true -> Result.Err(0)\n false -> Result.Ok(a / b)\n\nfn unwrapOr(r: Result<Int, Int>, d: Int) -> Int\n match r\n Result.Ok(v) -> v\n Result.Err(_) -> d\n\nfn chain(n: Int, acc: Int) -> Int\n match n == 0\n true -> acc\n false -> chain(n - 1, acc + unwrapOr(safeDivide(n * 10, n), 0))\n\nfn main() -> Int\n chain(400000, 0)\n";
70
71const LIST_WALK: &str = "\
72fn build(n: Int, acc: List<Int>) -> List<Int>\n match n == 0\n true -> acc\n false -> build(n - 1, List.prepend(n, acc))\n\nfn listLen(xs: List<Int>, acc: Int) -> Int\n match xs\n [] -> acc\n [h, ..t] -> listLen(t, acc + 1)\n\nfn walkFive(xs: List<Int>) -> Int\n listLen(xs, 0) + listLen(xs, 0) + listLen(xs, 0) + listLen(xs, 0) + listLen(xs, 0)\n\nfn main() -> Int\n walkFive(build(100000, []))\n";
73
74const SHAPES: &str = "\
75type Shape\n Circle(Float)\n Rect(Float, Float)\n Point\n\nfn area(s: Shape) -> Float\n match s\n Shape.Circle(r) -> r * r * 3.14159\n Shape.Rect(w, h) -> w * h\n Shape.Point -> 0.0\n\nfn sumAreas(n: Int, acc: Float) -> Float\n match n == 0\n true -> acc\n false -> sumAreas(n - 1, acc + area(Shape.Circle(1.0)) + area(Shape.Rect(3.0, 4.0)))\n\nfn main() -> Float\n sumAreas(300000, 0.0)\n";
76
77const RECORD_HEAVY: &str = "\
78record Point\n x: Int\n y: Int\n\nfn moveRight(p: Point) -> Point\n Point.update(p, x = p.x + 1)\n\nfn walk(n: Int, p: Point) -> Int\n match n == 0\n true -> p.x + p.y\n false -> walk(n - 1, moveRight(p))\n\nfn main() -> Int\n walk(400000, Point(x = 0, y = 0))\n";
79
80const STRING_BUILD: &str = "\
81fn repeat(n: Int, s: String, acc: String) -> String\n match n == 0\n true -> acc\n false -> repeat(n - 1, s, acc + s)\n\nfn main() -> Int\n r = repeat(20000, \"ab\", \"\")\n String.len(r)\n";
82
83const ERROR_PIPELINE: &str = "\
84fn validate(n: Int) -> Result<Int, String>\n match n < 0\n true -> Result.Err(\"negative\")\n false -> Result.Ok(n)\n\nfn transform(n: Int) -> Result<Int, String>\n match n > 1000\n true -> Result.Err(\"too large\")\n false -> Result.Ok(n * 2)\n\nfn pipeline(n: Int) -> Result<Int, String>\n v = validate(n)?\n transform(v)\n\nfn run(n: Int, acc: Int) -> Int\n match n == 0\n true -> acc\n false -> run(n - 1, acc + Result.withDefault(pipeline(n), 0))\n\nfn main() -> Int\n run(200000, 0)\n";
85
86const LIST_BUILTINS: &str = "\
87fn buildAndMeasure(n: Int, acc: List<Int>) -> Int\n match n == 0\n true -> List.len(acc)\n false -> buildAndMeasure(n - 1, List.prepend(n, acc))\n\nfn main() -> Int\n buildAndMeasure(400000, [])\n";
88
89const LIST_APPEND_SCAN: &str = "\
90fn build(n: Int, acc: List<Int>) -> List<Int>\n match n == 0\n true -> acc\n false -> build(n - 1, List.prepend(n, acc))\n\nfn sum(v: Vector<Int>, size: Int, i: Int, acc: Int) -> Int\n match i == size\n true -> acc\n false -> sum(v, size, i + 1, acc + Option.withDefault(Vector.get(v, i), 0))\n\nfn main() -> Int\n xs = List.reverse(build(12000, []))\n v = Vector.fromList(xs)\n sum(v, Vector.len(v), 0, 0)\n";
91
92const MIXED_REAL: &str = "\
93record Order\n id: Int\n amount: Int\n valid: Bool\n\nfn processOrder(o: Order) -> Result<Int, String>\n match o.valid\n true -> Result.Ok(o.amount * 2)\n false -> Result.Err(\"invalid\")\n\nfn processAll(n: Int, acc: Int) -> Int\n match n == 0\n true -> acc\n false -> processAll(n - 1, acc + Result.withDefault(processOrder(Order(id = n, amount = n * 10, valid = true)), 0))\n\nfn main() -> Int\n processAll(200000, 0)\n";
94
95const LIST_GET_OR: &str = "\
96fn build(n: Int, acc: List<Int>) -> List<Int>\n match n == 0\n true -> List.reverse(acc)\n false -> build(n - 1, List.prepend(n, acc))\n\nfn scan(v: Vector<Int>, size: Int, i: Int, acc: Int) -> Int\n match i == size\n true -> acc\n false -> scan(v, size, i + 1, acc + Option.withDefault(Vector.get(v, i), 0))\n\nfn main() -> Int\n xs = build(10000, [])\n v = Vector.fromList(xs)\n scan(v, 10000, 0, 0) + scan(v, 10000, 0, 0) + scan(v, 10000, 0, 0)\n";
97
98const JSON_ROUNDTRIP: &str = r#"module Bench
99 intent =
100 "Runtime benchmark case for the pure JSON module."
101 "Parses and re-serializes a nested object repeatedly."
102 depends [Data.Json]
103 effects [Console]
104
105fn sampleJson() -> String
106 "{{\"service\":\"aver\",\"version\":\"0.14\",\"score\":14,\"edge\":true,\"runtime\":{{\"target\":\"edge-wasm\",\"provider\":\"cloudflare\",\"packed\":true,\"preset\":\"cloudflare\"}},\"items\":[{{\"name\":\"json\",\"ok\":true,\"size\":136}},{{\"name\":\"wasm\",\"ok\":true,\"size\":4800}},{{\"name\":\"worker\",\"ok\":true,\"regions\":[\"waw\",\"iad\",\"nrt\"]}}],\"meta\":{{\"commit\":\"a9e6924\",\"notes\":[\"pure\",\"typed\",\"effects\"],\"limits\":{{\"cold_start\":0,\"external_fetch\":false}}}}}}"
107
108fn roundtripLen(raw: String) -> Int
109 match Data.Json.fromString(raw)
110 Result.Err(_) -> 0
111 Result.Ok(value) -> String.len(Data.Json.toString(value))
112
113fn loop(n: Int, raw: String, acc: Int) -> Int
114 match n == 0
115 true -> acc
116 false -> loop(n - 1, raw, acc + roundtripLen(raw))
117
118fn benchMain() -> Int
119 loop(1000, sampleJson(), 0)
120
121fn main() -> Unit
122 ! [Console.print]
123 Console.print("{benchMain()}")
124"#;
125
126pub const CORE_BENCH_CASES: &[CoreBenchCase] = &[
127 CoreBenchCase {
128 slug: "fib_25",
129 name: "fib(25)",
130 source: FIBONACCI,
131 },
132 CoreBenchCase {
133 slug: "sum_tco_10m",
134 name: "sum_tco(10M)",
135 source: SUM_TCO,
136 },
137 CoreBenchCase {
138 slug: "countdown_10m",
139 name: "countdown(10M)",
140 source: COUNTDOWN,
141 },
142 CoreBenchCase {
143 slug: "factorial_20",
144 name: "factorial(20) x 50K",
145 source: FACTORIAL_TCO,
146 },
147 CoreBenchCase {
148 slug: "nested_match_360k",
149 name: "nested_match(360K)",
150 source: NESTED_MATCH,
151 },
152 CoreBenchCase {
153 slug: "result_chain_400k",
154 name: "result_chain(400K)",
155 source: RESULT_CHAIN,
156 },
157 CoreBenchCase {
158 slug: "list_walk_100k",
159 name: "list_walk(100K x5)",
160 source: LIST_WALK,
161 },
162 CoreBenchCase {
163 slug: "shapes_300k",
164 name: "shapes(300K)",
165 source: SHAPES,
166 },
167 CoreBenchCase {
168 slug: "record_heavy_400k",
169 name: "record_heavy(400K)",
170 source: RECORD_HEAVY,
171 },
172 CoreBenchCase {
173 slug: "string_build_20k",
174 name: "string_build(20K)",
175 source: STRING_BUILD,
176 },
177 CoreBenchCase {
178 slug: "error_pipeline_200k",
179 name: "error_pipeline(200K)",
180 source: ERROR_PIPELINE,
181 },
182 CoreBenchCase {
183 slug: "list_builtins_400k",
184 name: "list_builtins(400K)",
185 source: LIST_BUILTINS,
186 },
187 CoreBenchCase {
188 slug: "list_append_scan_1k",
189 name: "list_append_scan(12K)",
190 source: LIST_APPEND_SCAN,
191 },
192 CoreBenchCase {
193 slug: "mixed_real_200k",
194 name: "mixed_real(200K)",
195 source: MIXED_REAL,
196 },
197 CoreBenchCase {
198 slug: "list_get_or_30k",
199 name: "list_get_or(30K)",
200 source: LIST_GET_OR,
201 },
202 CoreBenchCase {
203 slug: "json_roundtrip_1k",
204 name: "json_roundtrip(1K)",
205 source: JSON_ROUNDTRIP,
206 },
207];