aboutsummaryrefslogtreecommitdiff
path: root/src/net
diff options
context:
space:
mode:
authorimxyb <xyb4638@gmail.com>2020-10-28 21:26:04 +0000
committerEmmanuel Odeke <emmanuel@orijtech.com>2020-10-28 21:40:08 +0000
commit49a210eb87da6b7ac960cac990337ef4dc113b0d (patch)
tree3e5d210c140498d1749753200c1c9dcbd54ed64e /src/net
parent07d206f7698f4d45544a2f9b6051ede594ba04cc (diff)
downloadgo-49a210eb87da6b7ac960cac990337ef4dc113b0d.tar.gz
go-49a210eb87da6b7ac960cac990337ef4dc113b0d.zip
net/url: improve performance for resolvePath
benchmark compare results: 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% Change-Id: Ia69e9fb36abb5930ed49217b5219be62b57ec429 GitHub-Last-Rev: e16dd9f7415178120f67f472bf45a2b006e00a93 GitHub-Pull-Request: golang/go#42180 Reviewed-on: https://go-review.googlesource.com/c/go/+/264817 Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org> Trust: Emmanuel Odeke <emmanuel@orijtech.com>
Diffstat (limited to 'src/net')
-rw-r--r--src/net/url/url.go55
-rw-r--r--src/net/url/url_test.go8
2 files changed, 49 insertions, 14 deletions
diff --git a/src/net/url/url.go b/src/net/url/url.go
index c93def0bd7..d90f5f06b5 100644
--- a/src/net/url/url.go
+++ b/src/net/url/url.go
@@ -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.
diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go
index 92b15afad4..f02e4650d8 100644
--- a/src/net/url/url_test.go
+++ b/src/net/url/url_test.go
@@ -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
}{