Fork of daniellemaywood.uk/gleam — Wasm codegen work
1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2025 The Gleam contributors
3
4import benchmarks.{print_results}
5import gleam/list
6import gleamy/bench
7
8pub fn main() {
9 print_results([bench_odd_nums_between(), bench_count_ones(), bench_slice()])
10}
11
12fn bench_odd_nums_between() -> bench.BenchResults {
13 let odd_nums_between = fn(args) {
14 let #(start, end) = args
15 odd_nums_between(start, end, [])
16 }
17
18 bench.run(
19 [
20 bench.Input("[0, 100)", #(0, 100)),
21 bench.Input("[0, 1000)", #(0, 1000)),
22 bench.Input("[0, 10_000)", #(0, 10_000)),
23 bench.Input("[0, 100_000)", #(0, 100_000)),
24 bench.Input("[0, 1_000_000)", #(0, 1_000_000)),
25 ],
26 [bench.Function("odd_nums_between", odd_nums_between)],
27 [bench.Duration(1000), bench.Warmup(100)],
28 )
29}
30
31/// Returns a list of numbers from `start` up to, but not including, `end`.
32fn odd_nums_between(start: Int, end: Int, acc: List(Int)) -> List(Int) {
33 case start {
34 start if start >= end -> list.reverse(acc)
35 _ -> {
36 let acc = case start {
37 n if n % 2 == 1 -> [n, ..acc]
38 _ -> acc
39 }
40 odd_nums_between(start + 1, end, acc)
41 }
42 }
43}
44
45fn bench_count_ones() -> bench.BenchResults {
46 let create_list = fn(size) {
47 list.range(0, size)
48 |> list.map(fn(n) {
49 case n {
50 _ if n % 3 == 0 -> 1
51 _ -> 0
52 }
53 })
54 }
55
56 let count_ones = fn(list) { count_ones(list, 0) }
57
58 bench.run(
59 [
60 bench.Input("100 numbers", create_list(100)),
61 bench.Input("1000 numbers", create_list(1000)),
62 bench.Input("10_000 numbers", create_list(10_000)),
63 bench.Input("100_000 numbers", create_list(100_000)),
64 bench.Input("1_000_000 numbers", create_list(1_000_000)),
65 ],
66 [bench.Function("count_ones", count_ones)],
67 [bench.Duration(1000), bench.Warmup(100)],
68 )
69}
70
71/// Counts the number of ones in a list.
72fn count_ones(list: List(Int), count: Int) -> Int {
73 case list {
74 [] -> count
75 [1, ..tail] -> count_ones(tail, count + 1)
76 [_, ..tail] -> count_ones(tail, count)
77 }
78}
79
80fn bench_slice() -> bench.BenchResults {
81 let list = list.range(0, 1_000_000)
82
83 let slice = fn(args) {
84 let #(list, start, end) = args
85 slice(list, start, end, [])
86 }
87
88 bench.run(
89 [
90 bench.Input("[0, 1000)", #(list, 0, 1000)),
91 bench.Input("[0, 10_000)", #(list, 0, 10_000)),
92 bench.Input("[0, 100_000)", #(list, 0, 100_000)),
93 bench.Input("[999_000, 1_000_000)", #(list, 999_000, 1_000_000)),
94 bench.Input("[990_000, 1_000_000)", #(list, 990_000, 1_000_000)),
95 bench.Input("[900_000, 1_000_000)", #(list, 900_000, 1_000_000)),
96 bench.Input("[0, 1_000_000)", #(list, 0, 1_000_000)),
97 ],
98 [bench.Function("slice", slice)],
99 [bench.Duration(1000), bench.Warmup(100)],
100 )
101}
102
103/// Slices a list.
104fn slice(list: List(Int), start: Int, end: Int, acc: List(Int)) -> List(Int) {
105 case list {
106 // If the first element is before the slice, skip it.
107 [_, ..tail] if start > 0 -> {
108 slice(tail, start - 1, end - 1, acc)
109 }
110 // If the first element is within the slice, add it to the accumulator.
111 [head, ..tail] if end > 0 -> {
112 slice(tail, start - 1, end - 1, [head, ..acc])
113 }
114 // Otherwise, return the accumulator.
115 _ -> list.reverse(acc)
116 }
117}