Skip to content

Commit

Permalink
net/url: improve performance for resolvePath
Browse files Browse the repository at this point in the history
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: e16dd9f
GitHub-Pull-Request: #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>
  • Loading branch information
imxyb authored and odeke-em committed Oct 28, 2020
1 parent 07d206f commit 49a210e
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 14 deletions.
55 changes: 41 additions & 14 deletions src/net/url/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
8 changes: 8 additions & 0 deletions src/net/url/url_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}{
Expand Down

0 comments on commit 49a210e

Please sign in to comment.