This has no measurable impact on performance, but somewhat simplifies
the code.
updates #18177
name old time/op new time/op delta
EndToEnd 54.3µs ±10% 55.7µs ±12% ~ (p=0.505 n=8+8)
EndToEnd-6 31.4µs ± 9% 32.7µs ± 6% ~ (p=0.130 n=8+8)
EndToEnd-48 25.5µs ±12% 26.4µs ± 6% ~ (p=0.195 n=8+8)
EndToEndHTTP 53.7µs ± 8% 51.2µs ±15% ~ (p=0.463 n=7+8)
EndToEndHTTP-6 30.9µs ±18% 31.2µs ±14% ~ (p=0.959 n=8+8)
EndToEndHTTP-48 24.9µs ±11% 25.7µs ± 6% ~ (p=0.382 n=8+8)
EndToEndAsync 23.6µs ± 7% 24.2µs ± 6% ~ (p=0.383 n=7+7)
EndToEndAsync-6 21.0µs ±23% 22.0µs ±20% ~ (p=0.574 n=8+8)
EndToEndAsync-48 22.8µs ±16% 23.3µs ±13% ~ (p=0.721 n=8+8)
EndToEndAsyncHTTP 25.8µs ± 7% 24.7µs ±14% ~ (p=0.161 n=8+8)
EndToEndAsyncHTTP-6 22.1µs ±19% 22.6µs ±12% ~ (p=0.645 n=8+8)
EndToEndAsyncHTTP-48 22.9µs ±13% 22.1µs ±20% ~ (p=0.574 n=8+8)
name old alloc/op new alloc/op delta
EndToEnd 320B ± 0% 321B ± 0% ~ (p=1.000 n=8+8)
EndToEnd-6 320B ± 0% 321B ± 0% +0.20% (p=0.037 n=8+7)
EndToEnd-48 326B ± 0% 326B ± 0% ~ (p=0.124 n=8+8)
EndToEndHTTP 320B ± 0% 320B ± 0% ~ (all equal)
EndToEndHTTP-6 320B ± 0% 321B ± 0% ~ (p=0.077 n=8+8)
EndToEndHTTP-48 324B ± 0% 324B ± 0% ~ (p=1.000 n=8+8)
EndToEndAsync 227B ± 0% 227B ± 0% ~ (p=0.154 n=8+7)
EndToEndAsync-6 226B ± 0% 226B ± 0% ~ (all equal)
EndToEndAsync-48 230B ± 1% 229B ± 1% ~ (p=0.072 n=8+8)
EndToEndAsyncHTTP 227B ± 0% 227B ± 0% ~ (all equal)
EndToEndAsyncHTTP-6 226B ± 0% 226B ± 0% ~ (p=0.400 n=8+7)
EndToEndAsyncHTTP-48 228B ± 0% 228B ± 0% ~ (p=0.949 n=8+6)
name old allocs/op new allocs/op delta
EndToEnd 9.00 ± 0% 9.00 ± 0% ~ (all equal)
EndToEnd-6 9.00 ± 0% 9.00 ± 0% ~ (all equal)
EndToEnd-48 9.00 ± 0% 9.00 ± 0% ~ (all equal)
EndToEndHTTP 9.00 ± 0% 9.00 ± 0% ~ (all equal)
EndToEndHTTP-6 9.00 ± 0% 9.00 ± 0% ~ (all equal)
EndToEndHTTP-48 9.00 ± 0% 9.00 ± 0% ~ (all equal)
EndToEndAsync 8.00 ± 0% 8.00 ± 0% ~ (all equal)
EndToEndAsync-6 8.00 ± 0% 8.00 ± 0% ~ (all equal)
EndToEndAsync-48 8.00 ± 0% 8.00 ± 0% ~ (all equal)
EndToEndAsyncHTTP 8.00 ± 0% 8.00 ± 0% ~ (all equal)
EndToEndAsyncHTTP-6 8.00 ± 0% 8.00 ± 0% ~ (all equal)
EndToEndAsyncHTTP-48 8.00 ± 0% 8.00 ± 0% ~ (all equal)
https://perf.golang.org/search?q=upload:
20170428.2
Change-Id: I8ef7f71a7602302aa78c144327270dfce9211539
Reviewed-on: https://go-review.googlesource.com/42112
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
// Runs at /debug/rpc
func (server debugHTTP) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// Build a sorted version of the data.
- var services = make(serviceArray, len(server.serviceMap))
- i := 0
- server.mu.Lock()
- for sname, service := range server.serviceMap {
- services[i] = debugService{service, sname, make(methodArray, len(service.method))}
- j := 0
- for mname, method := range service.method {
- services[i].Method[j] = debugMethod{method, mname}
- j++
+ var services serviceArray
+ server.serviceMap.Range(func(snamei, svci interface{}) bool {
+ svc := svci.(*service)
+ ds := debugService{svc, snamei.(string), make(methodArray, 0, len(svc.method))}
+ for mname, method := range svc.method {
+ ds.Method = append(ds.Method, debugMethod{method, mname})
}
- sort.Sort(services[i].Method)
- i++
- }
- server.mu.Unlock()
+ sort.Sort(ds.Method)
+ services = append(services, ds)
+ return true
+ })
sort.Sort(services)
err := debug.Execute(w, services)
if err != nil {
// Server represents an RPC Server.
type Server struct {
- mu sync.RWMutex // protects the serviceMap
- serviceMap map[string]*service
+ serviceMap sync.Map // map[string]*service
reqLock sync.Mutex // protects freeReq
freeReq *Request
respLock sync.Mutex // protects freeResp
// NewServer returns a new Server.
func NewServer() *Server {
- return &Server{serviceMap: make(map[string]*service)}
+ return &Server{}
}
// DefaultServer is the default instance of *Server.
}
func (server *Server) register(rcvr interface{}, name string, useName bool) error {
- server.mu.Lock()
- defer server.mu.Unlock()
- if server.serviceMap == nil {
- server.serviceMap = make(map[string]*service)
- }
s := new(service)
s.typ = reflect.TypeOf(rcvr)
s.rcvr = reflect.ValueOf(rcvr)
log.Print(s)
return errors.New(s)
}
- if _, present := server.serviceMap[sname]; present {
- return errors.New("rpc: service already defined: " + sname)
- }
s.name = sname
// Install the methods
log.Print(str)
return errors.New(str)
}
- server.serviceMap[s.name] = s
+
+ if _, dup := server.serviceMap.LoadOrStore(sname, s); dup {
+ return errors.New("rpc: service already defined: " + sname)
+ }
return nil
}
return
}
-func (server *Server) readRequestHeader(codec ServerCodec) (service *service, mtype *methodType, req *Request, keepReading bool, err error) {
+func (server *Server) readRequestHeader(codec ServerCodec) (svc *service, mtype *methodType, req *Request, keepReading bool, err error) {
// Grab the request header.
req = server.getRequest()
err = codec.ReadRequestHeader(req)
methodName := req.ServiceMethod[dot+1:]
// Look up the request.
- server.mu.RLock()
- service = server.serviceMap[serviceName]
- server.mu.RUnlock()
- if service == nil {
+ svci, ok := server.serviceMap.Load(serviceName)
+ if !ok {
err = errors.New("rpc: can't find service " + req.ServiceMethod)
return
}
- mtype = service.method[methodName]
+ svc = svci.(*service)
+ mtype = svc.method[methodName]
if mtype == nil {
err = errors.New("rpc: can't find method " + req.ServiceMethod)
}