mirror of
https://github.com/valyala/fasthttp.git
synced 2026-06-14 15:56:44 +03:00
ioptimized decodeArgAppend a bit
Benchmark results on linux/amd64: name old time/op new time/op delta ArgsParse-4 72.8ns ± 2% 68.0ns ± 2% -6.59% (p=0.000 n=10+9) AppendUnquotedArgFastPath-4 20.4ns ± 2% 21.1ns ± 9% ~ (p=0.614 n=8+10) AppendUnquotedArgSlowPath-4 68.9ns ± 3% 70.4ns ± 6% ~ (p=0.148 n=9+10) URIParsePath-4 80.9ns ± 2% 78.7ns ± 2% -2.80% (p=0.000 n=10+10) URIParsePathQueryString-4 88.9ns ± 1% 86.3ns ± 1% -2.90% (p=0.000 n=10+8) URIParsePathQueryStringHash-4 95.7ns ± 8% 91.0ns ± 1% -4.88% (p=0.000 n=9+10) URIParseHostname-4 98.6ns ± 1% 95.4ns ± 1% -3.24% (p=0.000 n=10+10)
This commit is contained in:
@@ -428,15 +428,15 @@ func (s *argsScanner) next(kv *argsKV) bool {
|
||||
case '=':
|
||||
if isKey {
|
||||
isKey = false
|
||||
kv.key = decodeArgAppend(kv.key[:0], s.b[:i], true)
|
||||
kv.key = decodeArgAppend(kv.key[:0], s.b[:i])
|
||||
k = i + 1
|
||||
}
|
||||
case '&':
|
||||
if isKey {
|
||||
kv.key = decodeArgAppend(kv.key[:0], s.b[:i], true)
|
||||
kv.key = decodeArgAppend(kv.key[:0], s.b[:i])
|
||||
kv.value = kv.value[:0]
|
||||
} else {
|
||||
kv.value = decodeArgAppend(kv.value[:0], s.b[k:i], true)
|
||||
kv.value = decodeArgAppend(kv.value[:0], s.b[k:i])
|
||||
}
|
||||
s.b = s.b[i+1:]
|
||||
return true
|
||||
@@ -444,17 +444,17 @@ func (s *argsScanner) next(kv *argsKV) bool {
|
||||
}
|
||||
|
||||
if isKey {
|
||||
kv.key = decodeArgAppend(kv.key[:0], s.b, true)
|
||||
kv.key = decodeArgAppend(kv.key[:0], s.b)
|
||||
kv.value = kv.value[:0]
|
||||
} else {
|
||||
kv.value = decodeArgAppend(kv.value[:0], s.b[k:], true)
|
||||
kv.value = decodeArgAppend(kv.value[:0], s.b[k:])
|
||||
}
|
||||
s.b = s.b[len(s.b):]
|
||||
return true
|
||||
}
|
||||
|
||||
func decodeArgAppend(dst, src []byte, decodePlus bool) []byte {
|
||||
if bytes.IndexByte(src, '%') < 0 && (!decodePlus || bytes.IndexByte(src, '+') < 0) {
|
||||
func decodeArgAppend(dst, src []byte) []byte {
|
||||
if bytes.IndexByte(src, '%') < 0 && bytes.IndexByte(src, '+') < 0 {
|
||||
// fast path: src doesn't contain encoded chars
|
||||
return append(dst, src...)
|
||||
}
|
||||
@@ -466,15 +466,15 @@ func decodeArgAppend(dst, src []byte, decodePlus bool) []byte {
|
||||
if i+2 >= n {
|
||||
return append(dst, src[i:]...)
|
||||
}
|
||||
x1 := hexbyte2int(src[i+1])
|
||||
x2 := hexbyte2int(src[i+2])
|
||||
if x1 < 0 || x2 < 0 {
|
||||
x1 := hex2intTable[src[i+1]]
|
||||
x2 := hex2intTable[src[i+2]]
|
||||
if x1 == 16 || x2 == 16 {
|
||||
dst = append(dst, c)
|
||||
} else {
|
||||
dst = append(dst, byte(x1<<4|x2))
|
||||
dst = append(dst, x1<<4|x2)
|
||||
i += 2
|
||||
}
|
||||
} else if decodePlus && c == '+' {
|
||||
} else if c == '+' {
|
||||
dst = append(dst, ' ')
|
||||
} else {
|
||||
dst = append(dst, c)
|
||||
@@ -482,3 +482,36 @@ func decodeArgAppend(dst, src []byte, decodePlus bool) []byte {
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// decodeArgAppendNoPlus is almost identical to decodeArgAppend, but it doesn't
|
||||
// substitute '+' with ' '.
|
||||
//
|
||||
// The function is copy-pasted from decodeArgAppend due to the preformance
|
||||
// reasons only.
|
||||
func decodeArgAppendNoPlus(dst, src []byte) []byte {
|
||||
if bytes.IndexByte(src, '%') < 0 {
|
||||
// fast path: src doesn't contain encoded chars
|
||||
return append(dst, src...)
|
||||
}
|
||||
|
||||
// slow path
|
||||
for i, n := 0, len(src); i < n; i++ {
|
||||
c := src[i]
|
||||
if c == '%' {
|
||||
if i+2 >= n {
|
||||
return append(dst, src[i:]...)
|
||||
}
|
||||
x1 := hex2intTable[src[i+1]]
|
||||
x2 := hex2intTable[src[i+2]]
|
||||
if x1 == 16 || x2 == 16 {
|
||||
dst = append(dst, c)
|
||||
} else {
|
||||
dst = append(dst, x1<<4|x2)
|
||||
i += 2
|
||||
}
|
||||
} else {
|
||||
dst = append(dst, c)
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
+7
-11
@@ -265,8 +265,8 @@ func readHexInt(r *bufio.Reader) (int, error) {
|
||||
}
|
||||
return -1, err
|
||||
}
|
||||
k = hexbyte2int(c)
|
||||
if k < 0 {
|
||||
k = int(hex2intTable[c])
|
||||
if k == 16 {
|
||||
if i == 0 {
|
||||
return -1, errEmptyHexNum
|
||||
}
|
||||
@@ -324,23 +324,19 @@ func hexCharUpper(c byte) byte {
|
||||
var hex2intTable = func() []byte {
|
||||
b := make([]byte, 255)
|
||||
for i := byte(0); i < 255; i++ {
|
||||
c := byte(0)
|
||||
c := byte(16)
|
||||
if i >= '0' && i <= '9' {
|
||||
c = 1 + i - '0'
|
||||
c = i - '0'
|
||||
} else if i >= 'a' && i <= 'f' {
|
||||
c = 1 + i - 'a' + 10
|
||||
c = i - 'a' + 10
|
||||
} else if i >= 'A' && i <= 'F' {
|
||||
c = 1 + i - 'A' + 10
|
||||
c = i - 'A' + 10
|
||||
}
|
||||
b[i] = c
|
||||
}
|
||||
return b
|
||||
}()
|
||||
|
||||
func hexbyte2int(c byte) int {
|
||||
return int(hex2intTable[c]) - 1
|
||||
}
|
||||
|
||||
const toLower = 'a' - 'A'
|
||||
|
||||
var toLowerTable = func() [256]byte {
|
||||
@@ -401,7 +397,7 @@ func s2b(s string) []byte {
|
||||
//
|
||||
// dst may point to src. In this case src will be overwritten.
|
||||
func AppendUnquotedArg(dst, src []byte) []byte {
|
||||
return decodeArgAppend(dst, src, true)
|
||||
return decodeArgAppend(dst, src)
|
||||
}
|
||||
|
||||
// AppendQuotedArg appends url-encoded src to dst and returns appended dst.
|
||||
|
||||
@@ -75,18 +75,6 @@ func BenchmarkInt2HexByte(b *testing.B) {
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkHexByte2Int(b *testing.B) {
|
||||
buf := []byte("0A1B2c3d4E5F6C7a8D9ab7cd03ef")
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
var c byte
|
||||
for pb.Next() {
|
||||
for _, c = range buf {
|
||||
hexbyte2int(c)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkWriteHexInt(b *testing.B) {
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
var w ByteBuffer
|
||||
|
||||
@@ -277,7 +277,7 @@ func (u *URI) parse(host, uri []byte, h *RequestHeader) {
|
||||
func normalizePath(dst, src []byte) []byte {
|
||||
dst = dst[:0]
|
||||
dst = addLeadingSlash(dst, src)
|
||||
dst = decodeArgAppend(dst, src, false)
|
||||
dst = decodeArgAppendNoPlus(dst, src)
|
||||
|
||||
// remove duplicate slashes
|
||||
b := dst
|
||||
|
||||
Reference in New Issue
Block a user