diff --git a/README.md b/README.md index f7ad997..4d9257e 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 190428255 6.13 ns/op 0 B/op 0 allocs/op +Benchmark_ItoA/fiber (pos_num)-12 196626811 6.08 ns/op 0 B/op 0 allocs/op +Benchmark_ItoA/strconv.Itoa (pos_num)-12 80716807 14.33 ns/op 4 B/op 1 allocs/op +Benchmark_ItoA/strconv.Itoa (pos_num)-12 80445802 14.30 ns/op 4 B/op 1 allocs/op +Benchmark_ItoA/strconv.FormatInt_(pos_num)-12 81137728 14.30 ns/op 4 B/op 1 allocs/op +Benchmark_ItoA/strconv.FormatInt_(pos_num)-12 81345360 14.49 ns/op 4 B/op 1 allocs/op +Benchmark_ItoA/fiber (neg_num)-12 151121002 7.81 ns/op 0 B/op 0 allocs/op +Benchmark_ItoA/fiber (neg_num)-12 153566410 7.70 ns/op 0 B/op 0 allocs/op +Benchmark_ItoA/strconv.Itoa (neg_num)-12 84505304 13.75 ns/op 5 B/op 1 allocs/op +Benchmark_ItoA/strconv.Itoa (neg_num)-12 82524801 13.76 ns/op 5 B/op 1 allocs/op +Benchmark_ItoA/strconv.FormatInt (neg_num)-12 84884136 13.88 ns/op 5 B/op 1 allocs/op +Benchmark_ItoA/strconv.FormatInt (neg_num)-12 85829492 13.76 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..668b7d0 100644 --- a/convert.go +++ b/convert.go @@ -11,6 +11,8 @@ import ( "strings" "time" "unsafe" + + "github.com/valyala/fasthttp" ) // UnsafeString returns a string pointer without allocation @@ -151,3 +153,19 @@ 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 { + if n < 0 { + // Convert the number to positive + n = -n + dst = fasthttp.AppendUint(dst, n) + // add '-' in front of the number + dst = append(dst[:1], dst...) + dst[0] = '-' + + return dst + } + + return fasthttp.AppendUint(dst, n) +} diff --git a/convert_test.go b/convert_test.go index c1db239..256480f 100644 --- a/convert_test.go +++ b/convert_test.go @@ -6,6 +6,7 @@ package utils import ( "reflect" + "strconv" "testing" "time" @@ -232,6 +233,19 @@ 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)) +} + // go test -v -run=^$ -bench=ToString -benchmem -count=4 func Benchmark_ToString(b *testing.B) { for _, value := range dataTypeExamples { @@ -245,6 +259,19 @@ func Benchmark_ToString(b *testing.B) { } } +func Benchmark_ToString_string(b *testing.B) { + res := "" + expectedRes := "4242" + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + res = ToString(4242) + } + + require.Equal(b, expectedRes, res) +} + // go test -v -run=^$ -bench=ToString_concurrency -benchmem -count=4 func Benchmark_ToString_concurrency(b *testing.B) { for _, value := range dataTypeExamples { @@ -295,3 +322,70 @@ 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 := 4242 + number64 := int64(number) + numberString := "4242" + numberN := -4242 + number64N := int64(numberN) + numberNString := "-4242" + + var resB []byte + var resS string + b.Run("fiber (positiv number)", 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.Itoa (positiv number)", 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 (positiv number)", 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 (negative number)", 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.Itoa (negative number)", 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 (negative number)", 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) + }) +} diff --git a/go.mod b/go.mod index 237aa95..bf4f1ae 100644 --- a/go.mod +++ b/go.mod @@ -5,10 +5,14 @@ go 1.21 require ( github.com/google/uuid v1.6.0 github.com/stretchr/testify v1.9.0 + github.com/valyala/fasthttp v1.55.0 ) require ( + github.com/andybalholm/brotli v1.1.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 5697539..28f9b16 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,19 @@ +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8= +github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=