Skip to content

Commit de7dd9f

Browse files
committed
Add benchmarks for base:runtime.memory_*
1 parent 90820ea commit de7dd9f

File tree

1 file changed

+332
-0
lines changed

1 file changed

+332
-0
lines changed
Lines changed: 332 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,332 @@
1+
package benchmark_runtime
2+
3+
import "base:runtime"
4+
import "core:fmt"
5+
import "core:log"
6+
import "core:testing"
7+
import "core:time"
8+
9+
10+
// These are the normal, unoptimized algorithms.
11+
12+
plain_memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool {
13+
switch {
14+
case n == 0: return true
15+
case x == y: return true
16+
}
17+
a, b := ([^]byte)(x), ([^]byte)(y)
18+
length := uint(n)
19+
20+
for i := uint(0); i < length; i += 1 {
21+
if a[i] != b[i] {
22+
return false
23+
}
24+
}
25+
return true
26+
}
27+
28+
plain_memory_compare :: proc "contextless" (a, b: rawptr, n: int) -> int #no_bounds_check {
29+
switch {
30+
case a == b: return 0
31+
case a == nil: return -1
32+
case b == nil: return +1
33+
}
34+
35+
x := uintptr(a)
36+
y := uintptr(b)
37+
n := uintptr(n)
38+
39+
SU :: size_of(uintptr)
40+
fast := n/SU + 1
41+
offset := (fast-1)*SU
42+
curr_block := uintptr(0)
43+
if n < SU {
44+
fast = 0
45+
}
46+
47+
for /**/; curr_block < fast; curr_block += 1 {
48+
va := (^uintptr)(x + curr_block * size_of(uintptr))^
49+
vb := (^uintptr)(y + curr_block * size_of(uintptr))^
50+
if va ~ vb != 0 {
51+
for pos := curr_block*SU; pos < n; pos += 1 {
52+
a := (^byte)(x+pos)^
53+
b := (^byte)(y+pos)^
54+
if a ~ b != 0 {
55+
return -1 if (int(a) - int(b)) < 0 else +1
56+
}
57+
}
58+
}
59+
}
60+
61+
for /**/; offset < n; offset += 1 {
62+
a := (^byte)(x+offset)^
63+
b := (^byte)(y+offset)^
64+
if a ~ b != 0 {
65+
return -1 if (int(a) - int(b)) < 0 else +1
66+
}
67+
}
68+
69+
return 0
70+
}
71+
72+
plain_memory_compare_zero :: proc "contextless" (a: rawptr, n: int) -> int #no_bounds_check {
73+
x := uintptr(a)
74+
n := uintptr(n)
75+
76+
SU :: size_of(uintptr)
77+
fast := n/SU + 1
78+
offset := (fast-1)*SU
79+
curr_block := uintptr(0)
80+
if n < SU {
81+
fast = 0
82+
}
83+
84+
for /**/; curr_block < fast; curr_block += 1 {
85+
va := (^uintptr)(x + curr_block * size_of(uintptr))^
86+
if va ~ 0 != 0 {
87+
for pos := curr_block*SU; pos < n; pos += 1 {
88+
a := (^byte)(x+pos)^
89+
if a ~ 0 != 0 {
90+
return -1 if int(a) < 0 else +1
91+
}
92+
}
93+
}
94+
}
95+
96+
for /**/; offset < n; offset += 1 {
97+
a := (^byte)(x+offset)^
98+
if a ~ 0 != 0 {
99+
return -1 if int(a) < 0 else +1
100+
}
101+
}
102+
103+
return 0
104+
}
105+
106+
107+
sizes := [?]int {
108+
15, 16, 17,
109+
31, 32, 33,
110+
63, 64, 65,
111+
256,
112+
512,
113+
1024,
114+
1024 * 1024,
115+
1024 * 1024 * 1024,
116+
}
117+
118+
run_trial_size :: proc(p: proc "contextless" (rawptr, int) -> int, size: int, warmup: int, runs: int) -> (timing: time.Duration) {
119+
data := make([]u8, size)
120+
defer delete(data)
121+
data[size - 1] = 1
122+
123+
accumulator: int
124+
125+
for _ in 0..<warmup {
126+
accumulator += p(&data[0], size)
127+
}
128+
129+
for _ in 0..<runs {
130+
start := time.tick_now()
131+
accumulator += p(&data[0], size)
132+
done := time.tick_since(start)
133+
timing += done
134+
}
135+
136+
timing /= time.Duration(runs)
137+
138+
log.debug(accumulator)
139+
return
140+
}
141+
142+
run_trial_size_compare :: proc(p: proc "contextless" (rawptr, rawptr, int) -> bool, size: int, warmup: int, runs: int) -> (timing: time.Duration) {
143+
data_a := make([]u8, size)
144+
data_b := make([]u8, size)
145+
defer {
146+
delete(data_a)
147+
delete(data_b)
148+
}
149+
data_a[size - 1] = 1
150+
data_b[size - 1] = 2
151+
152+
accumulator: int
153+
154+
for _ in 0..<warmup {
155+
val := p(&data_a[0], &data_b[0], size)
156+
if !val {
157+
accumulator += 1
158+
}
159+
}
160+
161+
for _ in 0..<runs {
162+
start := time.tick_now()
163+
val := p(&data_a[0], &data_b[0], size)
164+
done := time.tick_since(start)
165+
if !val {
166+
accumulator += 1
167+
}
168+
timing += done
169+
}
170+
171+
timing /= time.Duration(runs)
172+
173+
log.debug(accumulator)
174+
return
175+
}
176+
177+
run_trial_size_compare_int :: proc(p: proc "contextless" (rawptr, rawptr, int) -> int, size: int, warmup: int, runs: int) -> (timing: time.Duration) {
178+
data_a := make([]u8, size)
179+
data_b := make([]u8, size)
180+
defer {
181+
delete(data_a)
182+
delete(data_b)
183+
}
184+
data_a[size - 1] = 1
185+
data_b[size - 1] = 2
186+
187+
accumulator: int
188+
189+
for _ in 0..<warmup {
190+
accumulator += p(&data_a[0], &data_b[0], size)
191+
}
192+
193+
for _ in 0..<runs {
194+
start := time.tick_now()
195+
accumulator += p(&data_a[0], &data_b[0], size)
196+
done := time.tick_since(start)
197+
timing += done
198+
}
199+
200+
timing /= time.Duration(runs)
201+
202+
log.debug(accumulator)
203+
return
204+
}
205+
206+
HOT :: 3
207+
208+
/* Memory Equal */
209+
210+
@test
211+
benchmark_plain_memory_equal_cold :: proc(t: ^testing.T) {
212+
report: string
213+
for size in sizes {
214+
timing := run_trial_size_compare(plain_memory_equal, size, 0, 1)
215+
report = fmt.tprintf("%s\n +++ % 8M | %v", report, size, timing)
216+
}
217+
log.info(report)
218+
}
219+
220+
@test
221+
benchmark_plain_memory_equal_hot :: proc(t: ^testing.T) {
222+
report: string
223+
for size in sizes {
224+
timing := run_trial_size_compare(plain_memory_equal, size, HOT, HOT)
225+
report = fmt.tprintf("%s\n +++ % 8M | %v", report, size, timing)
226+
}
227+
log.info(report)
228+
}
229+
230+
@test
231+
benchmark_simd_memory_equal_cold :: proc(t: ^testing.T) {
232+
report: string
233+
for size in sizes {
234+
timing := run_trial_size_compare(runtime.memory_equal, size, 0, 1)
235+
report = fmt.tprintf("%s\n +++ % 8M | %v", report, size, timing)
236+
}
237+
log.info(report)
238+
}
239+
240+
@test
241+
benchmark_simd_memory_equal_hot :: proc(t: ^testing.T) {
242+
report: string
243+
for size in sizes {
244+
timing := run_trial_size_compare(runtime.memory_equal, size, HOT, HOT)
245+
report = fmt.tprintf("%s\n +++ % 8M | %v", report, size, timing)
246+
}
247+
log.info(report)
248+
}
249+
250+
/* Memory Compare */
251+
252+
@test
253+
benchmark_plain_memory_compare_cold :: proc(t: ^testing.T) {
254+
report: string
255+
for size in sizes {
256+
timing := run_trial_size_compare_int(plain_memory_compare, size, 0, 1)
257+
report = fmt.tprintf("%s\n +++ % 8M | %v", report, size, timing)
258+
}
259+
log.info(report)
260+
}
261+
262+
@test
263+
benchmark_plain_memory_compare_hot :: proc(t: ^testing.T) {
264+
report: string
265+
for size in sizes {
266+
timing := run_trial_size_compare_int(plain_memory_compare, size, HOT, HOT)
267+
report = fmt.tprintf("%s\n +++ % 8M | %v", report, size, timing)
268+
}
269+
log.info(report)
270+
}
271+
272+
@test
273+
benchmark_simd_memory_compare_cold :: proc(t: ^testing.T) {
274+
report: string
275+
for size in sizes {
276+
timing := run_trial_size_compare_int(runtime.memory_compare, size, 0, 1)
277+
report = fmt.tprintf("%s\n +++ % 8M | %v", report, size, timing)
278+
}
279+
log.info(report)
280+
}
281+
282+
@test
283+
benchmark_simd_memory_compare_hot :: proc(t: ^testing.T) {
284+
report: string
285+
for size in sizes {
286+
timing := run_trial_size_compare_int(runtime.memory_compare, size, HOT, HOT)
287+
report = fmt.tprintf("%s\n +++ % 8M | %v", report, size, timing)
288+
}
289+
log.info(report)
290+
}
291+
292+
/* Memory Compare Zero */
293+
294+
@test
295+
benchmark_plain_memory_compare_zero_cold :: proc(t: ^testing.T) {
296+
report: string
297+
for size in sizes {
298+
timing := run_trial_size(plain_memory_compare_zero, size, 0, 1)
299+
report = fmt.tprintf("%s\n +++ % 8M | %v", report, size, timing)
300+
}
301+
log.info(report)
302+
}
303+
304+
@test
305+
benchmark_plain_memory_compare_zero_hot :: proc(t: ^testing.T) {
306+
report: string
307+
for size in sizes {
308+
timing := run_trial_size(plain_memory_compare_zero, size, HOT, HOT)
309+
report = fmt.tprintf("%s\n +++ % 8M | %v", report, size, timing)
310+
}
311+
log.info(report)
312+
}
313+
314+
@test
315+
benchmark_simd_memory_compare_zero_cold :: proc(t: ^testing.T) {
316+
report: string
317+
for size in sizes {
318+
timing := run_trial_size(runtime.memory_compare_zero, size, 0, 1)
319+
report = fmt.tprintf("%s\n +++ % 8M | %v", report, size, timing)
320+
}
321+
log.info(report)
322+
}
323+
324+
@test
325+
benchmark_simd_memory_compare_zero_hot :: proc(t: ^testing.T) {
326+
report: string
327+
for size in sizes {
328+
timing := run_trial_size(runtime.memory_compare_zero, size, HOT, HOT)
329+
report = fmt.tprintf("%s\n +++ % 8M | %v", report, size, timing)
330+
}
331+
log.info(report)
332+
}

0 commit comments

Comments
 (0)