Reuse bytes when cleaning the URL paths (#2179)
* path: use stack buffer in CleanPath to avoid allocs in common case Sync from https://github.com/julienschmidt/httprouter/commit/8222db13dbb3b3ab1eb84edb61a7030708b93bfa * path: sync test code from httprouter * path: update path_test.go to the latest code Co-authored-by: Bo-Yi Wu <appleboy.tw@gmail.com>
This commit is contained in:
@@ -5,6 +5,8 @@
|
||||
|
||||
package gin
|
||||
|
||||
const stackBufSize = 128
|
||||
|
||||
// cleanPath is the URL version of path.Clean, it returns a canonical URL path
|
||||
// for p, eliminating . and .. elements.
|
||||
//
|
||||
@@ -24,8 +26,11 @@ func cleanPath(p string) string {
|
||||
return "/"
|
||||
}
|
||||
|
||||
// Reasonably sized buffer on stack to avoid allocations in the common case.
|
||||
// If a larger buffer is required, it gets allocated dynamically.
|
||||
buf := make([]byte, 0, stackBufSize)
|
||||
|
||||
n := len(p)
|
||||
var buf []byte
|
||||
|
||||
// Invariants:
|
||||
// reading from path; r is index of next byte to process.
|
||||
@@ -37,7 +42,12 @@ func cleanPath(p string) string {
|
||||
|
||||
if p[0] != '/' {
|
||||
r = 0
|
||||
buf = make([]byte, n+1)
|
||||
|
||||
if n+1 > stackBufSize {
|
||||
buf = make([]byte, n+1)
|
||||
} else {
|
||||
buf = buf[:n+1]
|
||||
}
|
||||
buf[0] = '/'
|
||||
}
|
||||
|
||||
@@ -69,7 +79,7 @@ func cleanPath(p string) string {
|
||||
// can backtrack
|
||||
w--
|
||||
|
||||
if buf == nil {
|
||||
if len(buf) == 0 {
|
||||
for w > 1 && p[w] != '/' {
|
||||
w--
|
||||
}
|
||||
@@ -103,7 +113,7 @@ func cleanPath(p string) string {
|
||||
w++
|
||||
}
|
||||
|
||||
if buf == nil {
|
||||
if len(buf) == 0 {
|
||||
return p[:w]
|
||||
}
|
||||
return string(buf[:w])
|
||||
@@ -111,13 +121,20 @@ func cleanPath(p string) string {
|
||||
|
||||
// internal helper to lazily create a buffer if necessary.
|
||||
func bufApp(buf *[]byte, s string, w int, c byte) {
|
||||
if *buf == nil {
|
||||
b := *buf
|
||||
if len(b) == 0 {
|
||||
if s[w] == c {
|
||||
return
|
||||
}
|
||||
|
||||
*buf = make([]byte, len(s))
|
||||
copy(*buf, s[:w])
|
||||
if l := len(s); l > cap(b) {
|
||||
*buf = make([]byte, len(s))
|
||||
} else {
|
||||
*buf = (*buf)[:l]
|
||||
}
|
||||
b = *buf
|
||||
|
||||
copy(b, s[:w])
|
||||
}
|
||||
(*buf)[w] = c
|
||||
b[w] = c
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user