]> Cypherpunks repositories - gostls13.git/commitdiff
net/rpc: use a sync.Map for serviceMap instead of RWMutex
authorBryan C. Mills <bcmills@google.com>
Thu, 16 Feb 2017 23:07:29 +0000 (18:07 -0500)
committerBryan Mills <bcmills@google.com>
Fri, 28 Apr 2017 20:42:11 +0000 (20:42 +0000)
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>
src/net/rpc/debug.go
src/net/rpc/server.go

index 98b2c1c6c4aba0a50bc0c60bf2bf78eed4a9ea0a..a1d799ff19a1424258dd18123664a6476c343293 100644 (file)
@@ -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 {
index 1bc570ba524357e093963a868e55eb2fa5f4904d..29aae7ee7ff04b19815cfac7ebaf6b82266435d4 100644 (file)
@@ -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)
        }