8000 Go API: fast URL parsing; cache · NVIDIA/aistore@7026201 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Commit 7026201

Browse files
committed
Go API: fast URL parsing; cache
* static sync.Map to cache parsed URLs, "/v1/objects" path only Signed-off-by: Alex Aizman <alex.aizman@gmail.com>
1 parent e3605f4 commit 7026201

File tree

2 files changed

+63
-17
lines changed

2 files changed

+63
-17
lines changed

cmn/cos/cksum.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
// [NOTE]
2525
// - currently, we have only two crypto-secure types: sha256 and sha512 (SHA-2 family)
2626
// - see related object comparison logic in cmn/objattrs
27-
// - now that in the standard library, SHA-3 checksum(s) can be easily added (as in: ck.H = sha3.New512())
27+
// - now that SHA-3 is in the standard library, it can be easily added (as in: ck.H = sha3.New512())
2828
// not adding it yet, though, as there's no pressing need
2929

3030
// supported checksums

cmn/hreq.go

Lines changed: 62 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ import (
1010
"io"
1111
"net/http"
1212
"net/url"
13+
"strings"
1314
"sync"
1415
"time"
1516

17+
"github.com/NVIDIA/aistore/api/apc"
1618
"github.com/NVIDIA/aistore/cmn/cos"
1719
)
1820

@@ -38,6 +40,7 @@ var (
3840

3941
var (
4042
hpool sync.Pool
43+
hmap sync.Map
4144
req0 http.Request
4245
)
4346

@@ -125,27 +128,70 @@ func (u *HreqArgs) ReqWith(timeout time.Duration) (*http.Request, context.Contex
125128
return req, ctx, cancel, nil
126129
}
127130

128-
func newRequest(method, urls string) (*http.Request, error) {
129-
// 1. parse
130-
// TODO: split (before url.Path) and (after), and optimize
131-
u, err := url.Parse(urls)
132-
if err != nil {
133-
return nil, err
131+
func splitUpath(surl string) (prefix, path string) {
132+
const (
133+
minSchemeHostLen = 10
134+
)
135+
i := strings.Index(surl, apc.URLPathObjects.S)
136+
if i <= minSchemeHostLen {
137+
return "", ""
138+
}
139+
prefix, path = surl[:i], surl[i:]
140+
for _, c := range path { // reject control characters and space
141+
if c < 0x20 || c == 0x7f {
142+
return "", ""
143+
}
144+
}
145+
return prefix, path
146+
}
147+
148+
func newRequest(method, surl string) (*http.Request, error) {
149+
var (
150+
err error
151+
u *url.URL
152+
)
153+
// 1. fast path: split and reuse "/v1/objects/" url
154+
prefix, path := splitUpath(surl)
155+
if prefix == "" {
156+
u, err = url.Parse(surl)
157+
if err != nil {
158+
return nil, err
159+
}
160+
} else if parsed, ok := hmap.Load(prefix); ok {
161+
u = parsed.(*url.URL)
162+
tmp := *u // shallow copy (not to mutate the cached one)
163+
164+
p, q, ok := strings.Cut(path, "?")
165+
if ok {
166+
tmp.RawQuery = q
167+
} else {
168+
tmp.RawQuery = ""
169+
}
170+
decoded, _ := url.PathUnescape(p)
171+
tmp.Path = decoded
172+
tmp.RawPath = p
173+
174+
u = &tmp
175+
} else {
176+
u, err = url.Parse(surl)
177+
if err != nil {
178+
return nil, err
179+
}
180+
hmap.Store(prefix, u)
134181
}
135182

136183
// 2. reuse and initialize request
137184
req := hreqAlloc()
138-
{
139-
req.Method = method
140-
req.URL = u
141-
req.Proto = "HTTP/1.1"
142-
req.ProtoMajor = 1
143-
req.ProtoMinor = 1
144-
if req.Header == nil {
145-
req.Header = make(http.Header, 4)
146-
}
147-
req.Host = u.Host
185+
req.Method = method
186+
req.URL = u
187+
req.Proto = "HTTP/1.1"
188+
req.ProtoMajor = 1
189+
req.ProtoMinor = 1
190+
if req.Header == nil {
191+
req.Header = make(http.Header, 4)
148192
}
193+
req.Host = u.Host
194+
149195
return req, nil
150196
}
151197

0 commit comments

Comments
 (0)
0