mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
tstime: hand-implement parseInt for specific needs of rfc3339 parsing.
Makes parsing 4.6x faster. name old time/op new time/op delta ParseInt-12 32.1ns ± 1% 6.9ns ± 2% -78.55% (p=0.000 n=10+9) Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
parent
dc9b39e3fb
commit
b925e18f70
@ -8,7 +8,6 @@
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -105,10 +104,19 @@ func Parse3339(s string) (time.Time, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseInt(s string, dst *int) bool {
|
func parseInt(s string, dst *int) bool {
|
||||||
n, err := strconv.ParseInt(s, 10, 0)
|
if len(s) == 0 || len(s) > len("999999999") {
|
||||||
if err != nil || n < 0 {
|
*dst = 0
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
*dst = int(n)
|
n := 0
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
d := s[i] - '0'
|
||||||
|
if d > 9 {
|
||||||
|
*dst = 0
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
n = n*10 + int(d)
|
||||||
|
}
|
||||||
|
*dst = n
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,30 @@ func TestZoneOf(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseInt(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
in string
|
||||||
|
want int
|
||||||
|
ret bool
|
||||||
|
}{
|
||||||
|
{"", 0, false},
|
||||||
|
{"1", 1, true},
|
||||||
|
{"999999999", 999999999, true},
|
||||||
|
{"123456789", 123456789, true},
|
||||||
|
{"000000", 0, true},
|
||||||
|
{"bork", 0, false},
|
||||||
|
{"123bork", 0, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
var got int
|
||||||
|
gotRet := parseInt(tt.in, &got)
|
||||||
|
if gotRet != tt.ret || got != tt.want {
|
||||||
|
t.Errorf("parseInt(%q) = %v, %d; want %v, %d", tt.in, gotRet, got, tt.ret, tt.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkGoParse3339(b *testing.B) {
|
func BenchmarkGoParse3339(b *testing.B) {
|
||||||
run := func(in string) func(*testing.B) {
|
run := func(in string) func(*testing.B) {
|
||||||
return func(b *testing.B) {
|
return func(b *testing.B) {
|
||||||
@ -113,6 +137,7 @@ func BenchmarkGoParse3339InLocation(b *testing.B) {
|
|||||||
b.Fatalf("times don't stringify the same: %q vs %q", s1, s2)
|
b.Fatalf("times don't stringify the same: %q vs %q", s1, s2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_, err := time.ParseInLocation(time.RFC3339Nano, in, loc)
|
_, err := time.ParseInLocation(time.RFC3339Nano, in, loc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -153,3 +178,10 @@ func BenchmarkParse3339(b *testing.B) {
|
|||||||
b.Run("Z", run("2020-04-05T15:56:00.148487491Z"))
|
b.Run("Z", run("2020-04-05T15:56:00.148487491Z"))
|
||||||
b.Run("TZ", run("2020-04-05T15:56:00.148487491+08:00"))
|
b.Run("TZ", run("2020-04-05T15:56:00.148487491+08:00"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkParseInt(b *testing.B) {
|
||||||
|
var out int
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
parseInt("148487491", &out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user