diff --git a/README.md b/README.md index f7ad997..5b80fbd 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ pkg: github.com/gofiber/utils cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz ```go -// go test -benchmem -run=^$ -bench=Benchmark_ -count=2 +// go test -benchmem -run=^$ -bench=Benchmark_ -count=2 Benchmark_ToLowerBytes/fiber-12 29715831 36.44 ns/op 0 B/op 0 allocs/op Benchmark_ToLowerBytes/fiber-12 33316479 36.28 ns/op 0 B/op 0 allocs/op @@ -60,6 +60,19 @@ Benchmark_UnsafeBytes/default-12 52615048 22.33 ns/op Benchmark_ToString-12 22981430 51.72 ns/op 40 B/op 2 allocs/op Benchmark_ToString-12 22956476 52.93 ns/op 40 B/op 2 allocs/op +Benchmark_ItoA/fiber (pos_num)-12 186969812 6.25 ns/op 0 B/op 0 allocs/op +Benchmark_ItoA/fiber (pos_num)-12 193965686 6.16 ns/op 0 B/op 0 allocs/op +Benchmark_ItoA/strconv.Itoa (pos_num)-12 80716807 14.42 ns/op 4 B/op 1 allocs/op +Benchmark_ItoA/strconv.Itoa (pos_num)-12 80445802 14.85 ns/op 4 B/op 1 allocs/op +Benchmark_ItoA/strconv.FormatInt_(pos_num)-12 81137728 14.52 ns/op 4 B/op 1 allocs/op +Benchmark_ItoA/strconv.FormatInt_(pos_num)-12 81345360 14.51 ns/op 4 B/op 1 allocs/op +Benchmark_ItoA/fiber (neg_num)-12 192902048 6.18 ns/op 0 B/op 0 allocs/op +Benchmark_ItoA/fiber (neg_num)-12 194245189 6.14 ns/op 0 B/op 0 allocs/op +Benchmark_ItoA/strconv.Itoa (neg_num)-12 84505304 13.55 ns/op 5 B/op 1 allocs/op +Benchmark_ItoA/strconv.Itoa (neg_num)-12 82524801 13.54 ns/op 5 B/op 1 allocs/op +Benchmark_ItoA/strconv.FormatInt (neg_num)-12 84884136 13.63 ns/op 5 B/op 1 allocs/op +Benchmark_ItoA/strconv.FormatInt (neg_num)-12 85829492 13.63 ns/op 5 B/op 1 allocs/op + Benchmark_GetMIME/fiber-12 15782622 74.99 ns/op 0 B/op 0 allocs/op Benchmark_GetMIME/fiber-12 13992375 93.13 ns/op 0 B/op 0 allocs/op Benchmark_GetMIME/default-12 6825952 147.0 ns/op 0 B/op 0 allocs/op @@ -100,6 +113,7 @@ Benchmark_CalculateTimestamp/fiber-12 1000000000 0.2634 ns/op Benchmark_CalculateTimestamp/fiber-12 1000000000 0.2935 ns/op 0 B/op 0 allocs/op Benchmark_CalculateTimestamp/default-12 15740576 73.79 ns/op 0 B/op 0 allocs/op Benchmark_CalculateTimestamp/default-12 15789036 71.12 ns/op 0 B/op 0 allocs/op + ``` See all the benchmarks under https://gofiber.github.io/utils/ \ No newline at end of file diff --git a/convert.go b/convert.go index e21f322..3824401 100644 --- a/convert.go +++ b/convert.go @@ -151,3 +151,33 @@ func ToString(arg any, timeFormat ...string) string { return fmt.Sprint(arg) } } + +// AppendInt appends the string representation of the int n to dst and returns the extended buffer. +func AppendInt(dst []byte, n int) []byte { + isNegative := n < 0 + if isNegative { + // Convert the number to positive + n = -n + } + + var b [20]byte + buf := b[:] + i := len(buf) + var q int + for n >= 10 { + i-- + q = n / 10 + buf[i] = '0' + byte(n-q*10) + n = q + } + i-- + buf[i] = '0' + byte(n) + + if isNegative { + // add '-' in front of the number + dst = append(dst, '-') + } + dst = append(dst, buf[i:]...) + + return dst +} diff --git a/convert_test.go b/convert_test.go index c1db239..4b08b0f 100644 --- a/convert_test.go +++ b/convert_test.go @@ -5,7 +5,9 @@ package utils import ( + "math" "reflect" + "strconv" "testing" "time" @@ -232,6 +234,21 @@ func TestByteSize(t *testing.T) { } } +func Test_AppendInt(t *testing.T) { + t.Parallel() + + dst := make([]byte, 0) + + require.Equal(t, []byte("42"), AppendInt(dst, 42)) + require.Equal(t, []byte("1500"), AppendInt(dst, 1500)) + require.Equal(t, []byte("0"), AppendInt(dst, 0)) + require.Equal(t, []byte("-1"), AppendInt(dst, -1)) + require.Equal(t, []byte("-2"), AppendInt(dst, -2)) + require.Equal(t, []byte("-4500"), AppendInt(dst, -4500)) + require.Equal(t, []byte(strconv.Itoa(math.MaxInt)), AppendInt(dst, math.MaxInt)) + //require.Equal(t, []byte("-4500"), AppendInt(dst, math.MinInt+1)) +} + // go test -v -run=^$ -bench=ToString -benchmem -count=4 func Benchmark_ToString(b *testing.B) { for _, value := range dataTypeExamples { @@ -295,3 +312,90 @@ func Benchmark_UnsafeString(b *testing.B) { require.Equal(b, "Hello, World!", res) }) } + +// go test -v -run=^$ -bench=ItoA -benchmem -count=4 +func Benchmark_ItoA(b *testing.B) { + number := 2 + number64 := int64(number) + numberString := "2" + numberN := -2 + number64N := int64(numberN) + numberNString := "-2" + + var resB []byte + var resS string + b.Run("fiber (pos num)", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + + for n := 0; n < b.N; n++ { + resB = AppendInt(resB[:0], number) + } + require.Equal(b, []byte(numberString), resB) + }) + + b.Run("default - strconv.AppendInt (pos num)", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + + for n := 0; n < b.N; n++ { + resB = strconv.AppendInt(resB[:0], number64, 10) + } + require.Equal(b, []byte(numberString), resB) + }) + + b.Run("default - strconv.Itoa (pos num)", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + resS = strconv.Itoa(number) + } + require.Equal(b, numberString, resS) + }) + + b.Run("default - strconv.FormatInt (pos num)", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + resS = strconv.FormatInt(number64, 10) + } + require.Equal(b, numberString, resS) + }) + + b.Run("fiber (neg num)", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + resB = AppendInt(resB[:0], numberN) + } + require.Equal(b, []byte(numberNString), resB) + }) + + b.Run("default - strconv.AppendInt (neg num)", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + + for n := 0; n < b.N; n++ { + resB = strconv.AppendInt(resB[:0], number64N, 10) + } + require.Equal(b, []byte(numberNString), resB) + }) + + b.Run("default - strconv.Itoa (neg num)", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + resS = strconv.Itoa(numberN) + } + require.Equal(b, numberNString, resS) + }) + + b.Run("default - strconv.FormatInt (neg num)", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + resS = strconv.FormatInt(number64N, 10) + } + require.Equal(b, numberNString, resS) + }) +}