From: Bryan C. Mills Date: Thu, 16 Feb 2017 23:07:29 +0000 (-0500) Subject: net/rpc: use a sync.Map for serviceMap instead of RWMutex X-Git-Tag: go1.9beta1~397 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=ce5263ff8dc246676d84e511fbe385e907097b76;p=gostls13.git net/rpc: use a sync.Map for serviceMap instead of RWMutex 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 TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- diff --git a/src/net/rpc/debug.go b/src/net/rpc/debug.go index 98b2c1c6c4..a1d799ff19 100644 --- a/src/net/rpc/debug.go +++ b/src/net/rpc/debug.go @@ -71,20 +71,17 @@ type debugHTTP struct { // 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 { diff --git a/src/net/rpc/server.go b/src/net/rpc/server.go index 1bc570ba52..29aae7ee7f 100644 --- a/src/net/rpc/server.go +++ b/src/net/rpc/server.go @@ -187,8 +187,7 @@ type Response struct { // 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 @@ -197,7 +196,7 @@ type Server struct { // NewServer returns a new Server. func NewServer() *Server { - return &Server{serviceMap: make(map[string]*service)} + return &Server{} } // DefaultServer is the default instance of *Server. @@ -240,11 +239,6 @@ func (server *Server) RegisterName(name string, rcvr interface{}) error { } 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) @@ -262,9 +256,6 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) erro 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 @@ -283,7 +274,10 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) erro 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 } @@ -581,7 +575,7 @@ func (server *Server) readRequest(codec ServerCodec) (service *service, mtype *m 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) @@ -607,14 +601,13 @@ func (server *Server) readRequestHeader(codec ServerCodec) (service *service, mt 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) }