Skip to content

Commit bb21fcd

Browse files
elhimovoleg-jukovec
authored andcommitted
test: add benchmarks
Closes TNTP-3733
1 parent d70dadd commit bb21fcd

File tree

13 files changed

+1263
-7
lines changed

13 files changed

+1263
-7
lines changed

.github/workflows/testing.yaml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,18 @@ jobs:
5151
run: make coverage coveralls-deps coveralls
5252

5353
run-benchmarks:
54-
if: false
54+
if: (github.event_name == 'push') ||
55+
(github.event_name == 'pull_request' &&
56+
github.event.pull_request.head.repo.full_name != github.repository) ||
57+
(github.event_name == 'workflow_dispatch')
5558

5659
runs-on: ubuntu-latest
5760

61+
strategy:
62+
fail-fast: false
63+
matrix:
64+
golang: ['1.24', 'stable']
65+
5866
steps:
5967
- uses: actions/checkout@v4
6068
- uses: actions/setup-go@v5

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ testrace:
1717
@echo "Running tests with race flag"
1818
@go test ./... -count=100 -race
1919

20+
.PHONY: bench
21+
bench:
22+
@echo "Running benchmarks"
23+
@go test ./... -count=1 -bench=. -benchmem
24+
2025
.PHONY: coverage
2126
coverage:
2227
@echo "Running tests with coveralls"

README.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,76 @@ To run default set of tests directly:
281281
go test ./... -count=1
282282
```
283283

284+
## Benchmarking
285+
286+
Along with the approach supplied with `go-option` library pointer-based and slice-based approaches were benchmarked as well.
287+
288+
#### Init + Get (empty value)
289+
290+
```
291+
# int
292+
BenchmarkNoneInt/Typed-8 560566400 2.200 ns/op 0 B/op 0 allocs/op
293+
BenchmarkNoneInt/Generic-8 543332625 2.193 ns/op 0 B/op 0 allocs/op
294+
BenchmarkNoneInt/GenericPtr-8 487631254 2.474 ns/op 0 B/op 0 allocs/op
295+
BenchmarkNoneInt/GenericSlice-8 441513422 2.608 ns/op 0 B/op 0 allocs/op
296+
# string
297+
BenchmarkNoneString/Typed-8 170894025 6.545 ns/op 0 B/op 0 allocs/op
298+
BenchmarkNoneString/Generic-8 185572758 6.451 ns/op 0 B/op 0 allocs/op
299+
BenchmarkNoneString/GenericPtr-8 159143874 7.459 ns/op 0 B/op 0 allocs/op
300+
BenchmarkNoneString/GenericSlice-8 173419598 6.708 ns/op 0 B/op 0 allocs/op
301+
# struct
302+
BenchmarkNoneStruct/Typed-8 384845384 3.107 ns/op 0 B/op 0 allocs/op
303+
BenchmarkNoneStruct/Generic-8 415633797 2.884 ns/op 0 B/op 0 allocs/op
304+
BenchmarkNoneStruct/GenericPtr-8 331620082 3.580 ns/op 0 B/op 0 allocs/op
305+
BenchmarkNoneStruct/GenericSlice-8 387593746 3.115 ns/op 0 B/op 0 allocs/op
306+
```
307+
308+
#### Init + Get (non-empty value)
309+
310+
```
311+
# int
312+
BenchmarkSomeInt/Typed-8 499550200 2.231 ns/op 0 B/op 0 allocs/op
313+
BenchmarkSomeInt/Generic-8 321369986 3.491 ns/op 0 B/op 0 allocs/op
314+
BenchmarkSomeInt/GenericPtr-8 64221356 16.03 ns/op 8 B/op 1 allocs/op
315+
BenchmarkSomeInt/GenericSlice-8 71858188 16.53 ns/op 8 B/op 1 allocs/op
316+
# string
317+
BenchmarkSomeString/Typed-8 192472155 5.840 ns/op 0 B/op 0 allocs/op
318+
BenchmarkSomeString/Generic-8 197161162 6.471 ns/op 0 B/op 0 allocs/op
319+
BenchmarkSomeString/GenericPtr-8 16207524 98.67 ns/op 16 B/op 1 allocs/op
320+
BenchmarkSomeString/GenericSlice-8 12426998 100.4 ns/op 16 B/op 1 allocs/op
321+
# struct
322+
BenchmarkSomeStruct/Typed-8 358631294 3.407 ns/op 0 B/op 0 allocs/op
323+
BenchmarkSomeStruct/Generic-8 241312274 4.978 ns/op 0 B/op 0 allocs/op
324+
BenchmarkSomeStruct/GenericPtr-8 32534370 33.28 ns/op 24 B/op 1 allocs/op
325+
BenchmarkSomeStruct/GenericSlice-8 34119435 33.08 ns/op 24 B/op 1 allocs/op
326+
```
327+
328+
At this point we can see already that the alternatives (based on pointer and slice) require allocations while the approach implemented in `go-option` doesn't.
329+
330+
Now let's check encoding and decoding.
331+
332+
## Encode + Decode
333+
334+
```
335+
# int
336+
BenchmarkEncodeDecodeInt/Typed-8 46089481 22.66 ns/op 0 B/op 0 allocs/op
337+
BenchmarkEncodeDecodeInt/Generic-8 10070619 119.6 ns/op 32 B/op 2 allocs/op
338+
BenchmarkEncodeDecodeInt/GenericPtr-8 20202076 58.14 ns/op 16 B/op 2 allocs/op
339+
BenchmarkEncodeDecodeInt/GenericSlice-8 17400481 66.24 ns/op 24 B/op 3 allocs/op
340+
# string
341+
BenchmarkEncodeDecodeString/Typed-8 6053182 191.4 ns/op 8 B/op 1 allocs/op
342+
BenchmarkEncodeDecodeString/Generic-8 1891269 668.3 ns/op 56 B/op 3 allocs/op
343+
BenchmarkEncodeDecodeString/GenericPtr-8 1645518 659.2 ns/op 56 B/op 4 allocs/op
344+
BenchmarkEncodeDecodeString/GenericSlice-8 1464177 775.4 ns/op 72 B/op 5 allocs/op
345+
# struct
346+
BenchmarkEncodeDecodeStruct/Typed-8 12816339 90.85 ns/op 3 B/op 1 allocs/op
347+
BenchmarkEncodeDecodeStruct/Generic-8 2304001 532.5 ns/op 67 B/op 3 allocs/op
348+
BenchmarkEncodeDecodeStruct/GenericPtr-8 2071520 570.2 ns/op 75 B/op 4 allocs/op
349+
BenchmarkEncodeDecodeStruct/GenericSlice-8 2007445 587.4 ns/op 99 B/op 5 allocs/op
350+
```
351+
352+
As it can be seen generic implementation ~3-4 times slower than the typed one. Thus it is recommended to use pre-generated optionals for basic types supplied with `go-option` (`option.Int`, `option.String` etc.).
353+
284354
## License
285355
286356
BSD 2-Clause License

0 commit comments

Comments
 (0)