1pub struct CoreBenchCase {
2 pub slug: &'static str,
3 pub name: &'static str,
4 pub source: &'static str,
5}
6
7const FIBONACCI: &str = "\
8fn fib(n: Int) -> Int
9 match n < 2
10 true -> n
11 false -> fib(n - 1) + fib(n - 2)
12
13fn main() -> Int
14 fib(25)
15";
16
17const SUM_TCO: &str = "\
18fn sum(n: Int, acc: Int) -> Int
19 match n == 0
20 true -> acc
21 false -> sum(n - 1, acc + n)
22
23fn main() -> Int
24 sum(10000000, 0)
25";
26
27const COUNTDOWN: &str = "\
28fn countdown(n: Int) -> Int
29 match n == 0
30 true -> 0
31 false -> countdown(n - 1)
32
33fn main() -> Int
34 countdown(10000000)
35";
36
37const FACTORIAL_TCO: &str = "\
38fn fact(n: Int, acc: Int) -> Int
39 match n == 0
40 true -> acc
41 false -> fact(n - 1, acc * n)
42
43fn repeat(n: Int, acc: Int) -> Int
44 match n == 0
45 true -> acc
46 false -> repeat(n - 1, acc + Result.withDefault(Int.mod(fact(20, 1), 1000000), 0))
47
48fn main() -> Int
49 repeat(50000, 0)
50";
51
52const NESTED_MATCH: &str = "\
53fn 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";
54
55const RESULT_CHAIN: &str = "\
56fn 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";
57
58const LIST_WALK: &str = "\
59fn 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";
60
61const SHAPES: &str = "\
62type 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";
63
64const RECORD_HEAVY: &str = "\
65record 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";
66
67const STRING_BUILD: &str = "\
68fn 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";
69
70const ERROR_PIPELINE: &str = "\
71fn 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";
72
73const LIST_BUILTINS: &str = "\
74fn 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";
75
76const LIST_APPEND_SCAN: &str = "\
77fn 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";
78
79const MIXED_REAL: &str = "\
80record 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";
81
82const LIST_GET_OR: &str = "\
83fn 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";
84
85pub const CORE_BENCH_CASES: &[CoreBenchCase] = &[
86 CoreBenchCase {
87 slug: "fib_25",
88 name: "fib(25)",
89 source: FIBONACCI,
90 },
91 CoreBenchCase {
92 slug: "sum_tco_10m",
93 name: "sum_tco(10M)",
94 source: SUM_TCO,
95 },
96 CoreBenchCase {
97 slug: "countdown_10m",
98 name: "countdown(10M)",
99 source: COUNTDOWN,
100 },
101 CoreBenchCase {
102 slug: "factorial_20",
103 name: "factorial(20) x 50K",
104 source: FACTORIAL_TCO,
105 },
106 CoreBenchCase {
107 slug: "nested_match_360k",
108 name: "nested_match(360K)",
109 source: NESTED_MATCH,
110 },
111 CoreBenchCase {
112 slug: "result_chain_400k",
113 name: "result_chain(400K)",
114 source: RESULT_CHAIN,
115 },
116 CoreBenchCase {
117 slug: "list_walk_100k",
118 name: "list_walk(100K x5)",
119 source: LIST_WALK,
120 },
121 CoreBenchCase {
122 slug: "shapes_300k",
123 name: "shapes(300K)",
124 source: SHAPES,
125 },
126 CoreBenchCase {
127 slug: "record_heavy_400k",
128 name: "record_heavy(400K)",
129 source: RECORD_HEAVY,
130 },
131 CoreBenchCase {
132 slug: "string_build_20k",
133 name: "string_build(20K)",
134 source: STRING_BUILD,
135 },
136 CoreBenchCase {
137 slug: "error_pipeline_200k",
138 name: "error_pipeline(200K)",
139 source: ERROR_PIPELINE,
140 },
141 CoreBenchCase {
142 slug: "list_builtins_400k",
143 name: "list_builtins(400K)",
144 source: LIST_BUILTINS,
145 },
146 CoreBenchCase {
147 slug: "list_append_scan_1k",
148 name: "list_append_scan(12K)",
149 source: LIST_APPEND_SCAN,
150 },
151 CoreBenchCase {
152 slug: "mixed_real_200k",
153 name: "mixed_real(200K)",
154 source: MIXED_REAL,
155 },
156 CoreBenchCase {
157 slug: "list_get_or_30k",
158 name: "list_get_or(30K)",
159 source: LIST_GET_OR,
160 },
161];