Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AppendInt function with positive/negative number convertion to string #90

Closed
wants to merge 5 commits into from
Closed
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -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/
18 changes: 18 additions & 0 deletions convert.go
Original file line number Diff line number Diff line change
@@ -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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need a separate function for AppendUint that uses uint as param, else we won't be able to handle values bigger than 2,147,483,647

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The math module in Golang defines these:

MaxUint32 = 1<<32 - 1           // 4294967295
MaxUint64 = 1<<64 - 1           // 18446744073709551615

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)
}
81 changes: 81 additions & 0 deletions convert_test.go
Original file line number Diff line number Diff line change
@@ -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 {
@@ -295,3 +309,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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

positive*

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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

positive*

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)
})
}
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -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
)
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -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=