net/url: improve performance for `resolvePath`

```
benchmark                   old ns/op     new ns/op     delta
BenchmarkResolvePath-12     297           141           -52.53%

benchmark                   old allocs     new allocs     delta
BenchmarkResolvePath-12     5              3              -40.00%

benchmark                   old bytes     new bytes     delta
BenchmarkResolvePath-12     181           24            -86.74%
```
This commit is contained in:
imxyb 2020-10-24 11:01:54 +08:00
parent 15ead857db
commit e16dd9f741
2 changed files with 49 additions and 14 deletions

View File

@ -1000,25 +1000,52 @@ func resolvePath(base, ref string) string {
if full == "" {
return ""
}
src := strings.Split(full, "/")
dst := make([]string, 0, len(src))
for _, elem := range src {
switch elem {
case ".":
var (
last string
elem string
i int
dst strings.Builder
)
first := true
remaining := full
for i >= 0 {
i = strings.IndexByte(remaining, '/')
if i < 0 {
last, elem, remaining = remaining, remaining, ""
} else {
elem, remaining = remaining[:i], remaining[i+1:]
}
if elem == "." {
first = false
// drop
case "..":
if len(dst) > 0 {
dst = dst[:len(dst)-1]
continue
}
if elem == ".." {
str := dst.String()
index := strings.LastIndexByte(str, '/')
dst.Reset()
if index == -1 {
first = true
} else {
dst.WriteString(str[:index])
}
default:
dst = append(dst, elem)
} else {
if !first {
dst.WriteByte('/')
}
dst.WriteString(elem)
first = false
}
}
if last := src[len(src)-1]; last == "." || last == ".." {
// Add final slash to the joined path.
dst = append(dst, "")
if last == "." || last == ".." {
dst.WriteByte('/')
}
return "/" + strings.TrimPrefix(strings.Join(dst, "/"), "/")
return "/" + strings.TrimPrefix(dst.String(), "/")
}
// IsAbs reports whether the URL is absolute.

View File

@ -1114,6 +1114,14 @@ func TestResolvePath(t *testing.T) {
}
}
func BenchmarkResolvePath(b *testing.B) {
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
resolvePath("a/b/c", ".././d")
}
}
var resolveReferenceTests = []struct {
base, rel, expected string
}{