Published on

# Decimal benchmark

Authors

Today I will show you a simple benchmark between 2 library from previous post. Duel between https://github.com/shopspring/decimal with https://github.com/mercari/go-bps. The API of both library is similar in calculation but totally different with initialization, get amount, and conversion to string API.

In this benchmark I only compare simple calculation and string conversion.

## Simple add calculation

### helper function

`_16func decimalAdd(addition decimal.Decimal, n int) decimal.Decimal {_16 result := decimal.NewFromInt(0)_16 for i := 0; i < n; i++ {_16 result = result.Add(addition)_16 }_16_16 return result_16}_16_16func bpsAdd(addition *bps.BPS, n int) *bps.BPS {_16 result := bps.NewFromAmount(0)_16 for i := 0; i < n; i++ {_16 result = result.Add(addition)_16 }_16 return result_16}`

### Benchmark with 0.01 and 0.0000001 addition

`_54_54func BenchmarkShopspring001DecimalAdd(b *testing.B) {_54 addition := decimal.NewFromFloat(0.01)_54 for n := 0; n < b.N; n++ {_54 b.StopTimer()_54 b.StartTimer()_54 decimalAdd(addition, n)_54 }_54}_54_54func BenchmarkShopspringPPMDecimalAdd(b *testing.B) {_54 addition := decimal.NewFromFloat(0.000001)_54 for n := 0; n < b.N; n++ {_54 b.StopTimer()_54 b.StartTimer()_54 decimalAdd(addition, n)_54 }_54}_54_54func BenchmarkShopspring1000DecimalAdd(b *testing.B) {_54 addition := decimal.NewFromFloat(0.000001)_54 for n := 0; n < b.N; n++ {_54 b.StopTimer()_54 b.StartTimer()_54 decimalAdd(addition, 1000)_54 }_54}_54_54func BenchmarkMercari001BpsAdd(b *testing.B) {_54 addition := bps.NewFromPercentage(1)_54 for n := 0; n < b.N; n++ {_54 b.StopTimer()_54 b.StartTimer()_54 bpsAdd(addition, n)_54 }_54}_54_54func BenchmarkMercariPPMBpsAdd(b *testing.B) {_54 addition := bps.NewFromPPM(big.NewInt(1))_54 for n := 0; n < b.N; n++ {_54 b.StopTimer()_54 b.StartTimer()_54 bpsAdd(addition, n)_54 }_54}_54_54func BenchmarkMercari1000BpsAdd(b *testing.B) {_54 addition := bps.NewFromPercentage(1)_54 for n := 0; n < b.N; n++ {_54 b.StopTimer()_54 b.StartTimer()_54 bpsAdd(addition, 1000)_54 }_54}`

## Conversion to string

`_17func BenchmarkShopspringStringDecimalConvert(b *testing.B) {_17 value := decimal.NewFromFloat(0.000001)_17 for n := 0; n < b.N; n++ {_17 b.StopTimer()_17 b.StartTimer()_17 value.StringFixed(10)_17 }_17}_17_17func BenchmarkMercariStringBpsConvert(b *testing.B) {_17 value := bps.NewFromPPM(big.NewInt(1))_17 for n := 0; n < b.N; n++ {_17 b.StopTimer()_17 b.StartTimer()_17 value.FloatString(10)_17 }_17}`

## Result

`_14Running tool: /home/linuxbrew/.linuxbrew/bin/go test -benchmem -run=^\$ -bench ^(BenchmarkShopspring001DecimalAdd|BenchmarkShopspringPPMDecimalAdd|BenchmarkMercari001BpsAdd|BenchmarkMercariPPMBpsAdd|BenchmarkShopspringStringDecimalConvert|BenchmarkMercariStringBpsConvert)\$ github.com/h4ckm03d/golang-playground/6-practical-benchmark_14_14goos: linux_14goarch: amd64_14pkg: github.com/h4ckm03d/golang-playground/6-practical-benchmark_14cpu: Intel(R) Core(TM) i5-7500 CPU @ 3.40GHz_14BenchmarkShopspring001DecimalAdd-4 10000 389385 ns/op 400041 B/op 10003 allocs/op_14BenchmarkShopspringPPMDecimalAdd-4 10000 380516 ns/op 400088 B/op 10004 allocs/op_14BenchmarkMercari001BpsAdd-4 10000 1267632 ns/op 879983 B/op 40000 allocs/op_14BenchmarkMercariPPMBpsAdd-4 10000 1300074 ns/op 879983 B/op 40000 allocs/op_14BenchmarkShopspringStringDecimalConvert-4 1000000 1026 ns/op 240 B/op 12 allocs/op_14BenchmarkMercariStringBpsConvert-4 935912 1164 ns/op 320 B/op 16 allocs/op_14PASS_14ok github.com/h4ckm03d/golang-playground/6-practical-benchmark 63.276s`

The result of calculation above show the `shopspring/decimal` is faster and memory allocation is smaller compare to `mercari/go-bps`. But the string conversion of result is pretty similar compared to the calculation result and the winner still `shopspring/decimal`.

So the winner is `shopspring/decimal` and I think both of them is still fast because the slowest operation takes `1267632ns ~ 1.267632ms ~ 0.001267632 seconds`. The choice is yours now, which one do you prefer?

Check complete codes in the https://github.com/h4ckm03d/golang-playground/blob/master/6-practical-benchmark/decimal_test.go