diff --git a/README.md b/README.md index fde688b..6e59688 100644 --- a/README.md +++ b/README.md @@ -10,72 +10,96 @@ A collection of common functions but with better performance, less allocations a ## Benchmarks +Environment: +goos: darwin +goarch: amd64 +pkg: github.com/gofiber/utils +cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz + ```go // go test -benchmem -run=^$ -bench=Benchmark_ -count=2 -Benchmark_ToLowerBytes/fiber-16 51138252 22.61 ns/op 0 B/op 0 allocs/op -Benchmark_ToLowerBytes/fiber-16 52126545 22.63 ns/op 0 B/op 0 allocs/op -Benchmark_ToLowerBytes/default-16 16114736 72.76 ns/op 80 B/op 1 allocs/op -Benchmark_ToLowerBytes/default-16 16651540 73.85 ns/op 80 B/op 1 allocs/op - -Benchmark_ToUpperBytes/fiber-16 52127224 22.62 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpperBytes/fiber-16 54283167 22.86 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpperBytes/default-16 14060098 84.12 ns/op 80 B/op 1 allocs/op -Benchmark_ToUpperBytes/default-16 14183122 84.51 ns/op 80 B/op 1 allocs/op - -Benchmark_EqualFoldBytes/fiber-16 29240264 41.22 ns/op 0 B/op 0 allocs/op -Benchmark_EqualFoldBytes/fiber-16 28535826 40.84 ns/op 0 B/op 0 allocs/op -Benchmark_EqualFoldBytes/default-16 7929867 150.2 ns/op 0 B/op 0 allocs/op -Benchmark_EqualFoldBytes/default-16 7935478 149.7 ns/op 0 B/op 0 allocs/op - -Benchmark_EqualFold/fiber-16 35442768 34.25 ns/op 0 B/op 0 allocs/op -Benchmark_EqualFold/fiber-16 35946870 34.96 ns/op 0 B/op 0 allocs/op -Benchmark_EqualFold/default-16 8942130 133.5 ns/op 0 B/op 0 allocs/op -Benchmark_EqualFold/default-16 8977231 134.3 ns/op 0 B/op 0 allocs/op - -Benchmark_UUID/fiber-16 30726213 40.57 ns/op 48 B/op 1 allocs/op -Benchmark_UUID/fiber-16 26539394 40.25 ns/op 48 B/op 1 allocs/op -Benchmark_UUID/default-16 4737199 247.5 ns/op 168 B/op 6 allocs/op -Benchmark_UUID/default-16 4603738 250.8 ns/op 168 B/op 6 allocs/op - -Benchmark_ConvertToBytes/fiber-16 62450884 19.41 ns/op 0 B/op 0 allocs/op -Benchmark_ConvertToBytes/fiber-16 52123602 19.53 ns/op 0 B/op 0 allocs/op - -Benchmark_UnsafeString/unsafe-16 1000000000 0.4496 ns/op 0 B/op 0 allocs/op -Benchmark_UnsafeString/unsafe-16 1000000000 0.4488 ns/op 0 B/op 0 allocs/op -Benchmark_UnsafeString/default-16 79925935 13.99 ns/op 16 B/op 1 allocs/op -Benchmark_UnsafeString/default-16 85637211 14.35 ns/op 16 B/op 1 allocs/op - -Benchmark_UnsafeBytes/unsafe-16 540970148 2.214 ns/op 0 B/op 0 allocs/op -Benchmark_UnsafeBytes/unsafe-16 543356940 2.212 ns/op 0 B/op 0 allocs/op -Benchmark_UnsafeBytes/default-16 68896224 17.19 ns/op 16 B/op 1 allocs/op -Benchmark_UnsafeBytes/default-16 70560426 17.05 ns/op 16 B/op 1 allocs/op - -Benchmark_ToString-16 29504036 39.57 ns/op 40 B/op 2 allocs/op -Benchmark_ToString-16 30738334 38.89 ns/op 40 B/op 2 allocs/op - -Benchmark_GetMIME/fiber-16 28207086 41.84 ns/op 0 B/op 0 allocs/op -Benchmark_GetMIME/fiber-16 28165773 41.83 ns/op 0 B/op 0 allocs/op -Benchmark_GetMIME/default-16 12583132 94.04 ns/op 0 B/op 0 allocs/op -Benchmark_GetMIME/default-16 12829614 93.50 ns/op 0 B/op 0 allocs/op - -Benchmark_ParseVendorSpecificContentType/vendorContentType-16 30267411 38.72 ns/op 16 B/op 1 allocs/op -Benchmark_ParseVendorSpecificContentType/vendorContentType-16 28543563 38.60 ns/op 16 B/op 1 allocs/op -Benchmark_ParseVendorSpecificContentType/defaultContentType-16 249869286 4.830 ns/op 0 B/op 0 allocs/op -Benchmark_ParseVendorSpecificContentType/defaultContentType-16 248999592 4.805 ns/op 0 B/op 0 allocs/op - -Benchmark_StatusMessage/fiber-16 1000000000 0.6744 ns/op 0 B/op 0 allocs/op -Benchmark_StatusMessage/fiber-16 1000000000 0.6788 ns/op 0 B/op 0 allocs/op -Benchmark_StatusMessage/default-16 446818872 2.664 ns/op 0 B/op 0 allocs/op -Benchmark_StatusMessage/default-16 447009616 2.661 ns/op 0 B/op 0 allocs/op - -Benchmark_ToUpper/fiber-16 20480331 56.50 ns/op 80 B/op 1 allocs/op -Benchmark_ToUpper/fiber-16 21541200 56.65 ns/op 80 B/op 1 allocs/op -Benchmark_ToUpper/default-16 8433409 141.2 ns/op 80 B/op 1 allocs/op -Benchmark_ToUpper/default-16 8473737 141.1 ns/op 80 B/op 1 allocs/op - -Benchmark_ToLower/fiber-16 27248326 44.68 ns/op 80 B/op 1 allocs/op -Benchmark_ToLower/fiber-16 26918443 44.70 ns/op 80 B/op 1 allocs/op -Benchmark_ToLower/default-16 8447336 141.9 ns/op 80 B/op 1 allocs/op -Benchmark_ToLower/default-16 8423156 140.6 ns/op 80 B/op 1 allocs/op +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 +Benchmark_ToLowerBytes/default-12 11894427 96.98 ns/op 80 B/op 1 allocs/op +Benchmark_ToLowerBytes/default-12 12217050 97.43 ns/op 80 B/op 1 allocs/op + +Benchmark_ToUpperBytes/fiber-12 22042162 46.92 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpperBytes/fiber-12 25859680 46.43 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpperBytes/default-12 10015346 117.2 ns/op 80 B/op 1 allocs/op +Benchmark_ToUpperBytes/default-12 10185375 117.8 ns/op 80 B/op 1 allocs/op + +Benchmark_EqualFoldBytes/fiber-12 22944849 47.14 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFoldBytes/fiber-12 26006342 46.82 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFoldBytes/default-12 5222006 222.5 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFoldBytes/default-12 5349398 223.2 ns/op 0 B/op 0 allocs/op + +Benchmark_EqualFold/fiber-12 24761037 48.63 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold/fiber-12 24159073 48.63 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold/default-12 6322188 191.5 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold/default-12 6319070 193.5 ns/op 0 B/op 0 allocs/op + +Benchmark_UUID/fiber-12 22061482 49.13 ns/op 48 B/op 1 allocs/op +Benchmark_UUID/fiber-12 24123198 48.40 ns/op 48 B/op 1 allocs/op +Benchmark_UUID/default-12 3581961 336.9 ns/op 168 B/op 6 allocs/op +Benchmark_UUID/default-12 3465946 344.8 ns/op 168 B/op 6 allocs/op + +Benchmark_ConvertToBytes/fiber-12 53392819 23.19 ns/op 0 B/op 0 allocs/op +Benchmark_ConvertToBytes/fiber-12 51117225 23.32 ns/op 0 B/op 0 allocs/op + +Benchmark_UnsafeString/unsafe-12 1000000000 0.5672 ns/op 0 B/op 0 allocs/op +Benchmark_UnsafeString/unsafe-12 1000000000 0.5683 ns/op 0 B/op 0 allocs/op +Benchmark_UnsafeString/default-12 64000897 18.45 ns/op 16 B/op 1 allocs/op +Benchmark_UnsafeString/default-12 64138909 18.13 ns/op 16 B/op 1 allocs/op + +Benchmark_UnsafeBytes/unsafe-12 474777096 2.539 ns/op 0 B/op 0 allocs/op +Benchmark_UnsafeBytes/unsafe-12 469340781 2.535 ns/op 0 B/op 0 allocs/op +Benchmark_UnsafeBytes/default-12 53125656 22.15 ns/op 16 B/op 1 allocs/op +Benchmark_UnsafeBytes/default-12 52615048 22.33 ns/op 16 B/op 1 allocs/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_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 +Benchmark_GetMIME/default-12 9158227 132.5 ns/op 0 B/op 0 allocs/op + +ParseVendorSpecificContentType +Benchmark_Parse.../vendorContentType-12 21334663 50.24 ns/op 16 B/op 1 allocs/op +Benchmark_Parse.../vendorContentType-12 23121808 51.20 ns/op 16 B/op 1 allocs/op +Benchmark_Parse.../defaultContentType-12 154423909 6.772 ns/op 0 B/op 0 allocs/op +Benchmark_Parse.../defaultContentType-12 183285117 6.662 ns/op 0 B/op 0 allocs/op + +Benchmark_StatusMessage/fiber-12 1000000000 0.9796 ns/op 0 B/op 0 allocs/op +Benchmark_StatusMessage/fiber-12 1000000000 0.9706 ns/op 0 B/op 0 allocs/op +Benchmark_StatusMessage/default-12 380260562 2.989 ns/op 0 B/op 0 allocs/op +Benchmark_StatusMessage/default-12 403639642 3.124 ns/op 0 B/op 0 allocs/op + +Benchmark_IsIPv4/fiber-12 53576214 21.07 ns/op 0 B/op 0 allocs/op +Benchmark_IsIPv4/fiber-12 62672907 22.04 ns/op 0 B/op 0 allocs/op +Benchmark_IsIPv4/default-12 21204613 62.23 ns/op 16 B/op 1 allocs/op +Benchmark_IsIPv4/default-12 21399847 56.61 ns/op 16 B/op 1 allocs/op + +Benchmark_IsIPv6/fiber-12 16754995 72.46 ns/op 0 B/op 0 allocs/op +Benchmark_IsIPv6/fiber-12 17080897 74.31 ns/op 0 B/op 0 allocs/op +Benchmark_IsIPv6/default-12 8160195 124.5 ns/op 16 B/op 1 allocs/op +Benchmark_IsIPv6/default-12 9415326 119.8 ns/op 16 B/op 1 allocs/op + +Benchmark_ToUpper/fiber-12 13175154 81.67 ns/op 80 B/op 1 allocs/op +Benchmark_ToUpper/fiber-12 14285533 77.27 ns/op 80 B/op 1 allocs/op +Benchmark_ToUpper/default-12 5332206 231.8 ns/op 80 B/op 1 allocs/op +Benchmark_ToUpper/default-12 5364650 236.0 ns/op 80 B/op 1 allocs/op + +Benchmark_ToLower/fiber-12 12996409 80.24 ns/op 80 B/op 1 allocs/op +Benchmark_ToLower/fiber-12 16539536 69.27 ns/op 80 B/op 1 allocs/op +Benchmark_ToLower/default-12 5132185 222.5 ns/op 80 B/op 1 allocs/op +Benchmark_ToLower/default-12 5158561 225.3 ns/op 80 B/op 1 allocs/op + +Benchmark_CalculateTimestamp/fiber-12 1000000000 0.2634 ns/op 0 B/op 0 allocs/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/time.go b/time.go new file mode 100644 index 0000000..8ea13c2 --- /dev/null +++ b/time.go @@ -0,0 +1,32 @@ +package utils + +import ( + "sync" + "sync/atomic" + "time" +) + +var ( + timestampTimer sync.Once + // Timestamp please start the timer function before you use this value + // please load the value with atomic `atomic.LoadUint32(&utils.Timestamp)` + Timestamp uint32 +) + +// StartTimeStampUpdater starts a concurrent function which stores the timestamp to an atomic value per second, +// which is much better for performance than determining it at runtime each time +func StartTimeStampUpdater() { + timestampTimer.Do(func() { + // set initial value + atomic.StoreUint32(&Timestamp, uint32(time.Now().Unix())) + go func(sleep time.Duration) { + ticker := time.NewTicker(sleep) + defer ticker.Stop() + + for t := range ticker.C { + // update timestamp + atomic.StoreUint32(&Timestamp, uint32(t.Unix())) + } + }(1 * time.Second) // duration + }) +} diff --git a/time_test.go b/time_test.go new file mode 100644 index 0000000..2f74d55 --- /dev/null +++ b/time_test.go @@ -0,0 +1,47 @@ +package utils + +import ( + "sync/atomic" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func checkTimeStamp(t testing.TB, expectedCurrent, actualCurrent uint32) { + // test with some buffer in front and back of the expectedCurrent time -> because of the timing on the work machine + require.Equal(t, true, actualCurrent >= expectedCurrent-1 || actualCurrent <= expectedCurrent+1) +} + +func Test_TimeStampUpdater(t *testing.T) { + t.Parallel() + + StartTimeStampUpdater() + + now := uint32(time.Now().Unix()) + checkTimeStamp(t, now, atomic.LoadUint32(&Timestamp)) + // one second later + time.Sleep(1 * time.Second) + checkTimeStamp(t, now+1, atomic.LoadUint32(&Timestamp)) + // two seconds later + time.Sleep(1 * time.Second) + checkTimeStamp(t, now+2, atomic.LoadUint32(&Timestamp)) +} + +func Benchmark_CalculateTimestamp(b *testing.B) { + StartTimeStampUpdater() + + var res uint32 + b.Run("fiber", func(b *testing.B) { + for n := 0; n < b.N; n++ { + res = atomic.LoadUint32(&Timestamp) + } + checkTimeStamp(b, uint32(time.Now().Unix()), res) + }) + b.Run("default", func(b *testing.B) { + for n := 0; n < b.N; n++ { + res = uint32(time.Now().Unix()) + } + checkTimeStamp(b, uint32(time.Now().Unix()), res) + }) +}