diff options
author | imxyb <xyb4638@gmail.com> | 2020-10-28 21:26:04 +0000 |
---|---|---|
committer | Emmanuel Odeke <emmanuel@orijtech.com> | 2020-10-28 21:40:08 +0000 |
commit | 49a210eb87da6b7ac960cac990337ef4dc113b0d (patch) | |
tree | 3e5d210c140498d1749753200c1c9dcbd54ed64e /src/net | |
parent | 07d206f7698f4d45544a2f9b6051ede594ba04cc (diff) | |
download | go-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.go | 55 | ||||
-rw-r--r-- | src/net/url/url_test.go | 8 |
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 }{ |