Skip to content

Commit ce5263f

Browse files
author
Bryan C. Mills
committed
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent d6ce7e4 commit ce5263f

File tree

2 files changed

+21
-31
lines changed

2 files changed

+21
-31
lines changed

src/net/rpc/debug.go

+10-13
Original file line numberDiff line numberDiff line change
@@ -71,20 +71,17 @@ type debugHTTP struct {
7171
// Runs at /debug/rpc
7272
func (server debugHTTP) ServeHTTP(w http.ResponseWriter, req *http.Request) {
7373
// Build a sorted version of the data.
74-
var services = make(serviceArray, len(server.serviceMap))
75-
i := 0
76-
server.mu.Lock()
77-
for sname, service := range server.serviceMap {
78-
services[i] = debugService{service, sname, make(methodArray, len(service.method))}
79-
j := 0
80-
for mname, method := range service.method {
81-
services[i].Method[j] = debugMethod{method, mname}
82-
j++
74+
var services serviceArray
75+
server.serviceMap.Range(func(snamei, svci interface{}) bool {
76+
svc := svci.(*service)
77+
ds := debugService{svc, snamei.(string), make(methodArray, 0, len(svc.method))}
78+
for mname, method := range svc.method {
79+
ds.Method = append(ds.Method, debugMethod{method, mname})
8380
}
84-
sort.Sort(services[i].Method)
85-
i++
86-
}
87-
server.mu.Unlock()
81+
sort.Sort(ds.Method)
82+
services = append(services, ds)
83+
return true
84+
})
8885
sort.Sort(services)
8986
err := debug.Execute(w, services)
9087
if err != nil {

src/net/rpc/server.go

+11-18
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,7 @@ type Response struct {
187187

188188
// Server represents an RPC Server.
189189
type Server struct {
190-
mu sync.RWMutex // protects the serviceMap
191-
serviceMap map[string]*service
190+
serviceMap sync.Map // map[string]*service
192191
reqLock sync.Mutex // protects freeReq
193192
freeReq *Request
194193
respLock sync.Mutex // protects freeResp
@@ -197,7 +196,7 @@ type Server struct {
197196

198197
// NewServer returns a new Server.
199198
func NewServer() *Server {
200-
return &Server{serviceMap: make(map[string]*service)}
199+
return &Server{}
201200
}
202201

203202
// DefaultServer is the default instance of *Server.
@@ -240,11 +239,6 @@ func (server *Server) RegisterName(name string, rcvr interface{}) error {
240239
}
241240

242241
func (server *Server) register(rcvr interface{}, name string, useName bool) error {
243-
server.mu.Lock()
244-
defer server.mu.Unlock()
245-
if server.serviceMap == nil {
246-
server.serviceMap = make(map[string]*service)
247-
}
248242
s := new(service)
249243
s.typ = reflect.TypeOf(rcvr)
250244
s.rcvr = reflect.ValueOf(rcvr)
@@ -262,9 +256,6 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) erro
262256
log.Print(s)
263257
return errors.New(s)
264258
}
265-
if _, present := server.serviceMap[sname]; present {
266-
return errors.New("rpc: service already defined: " + sname)
267-
}
268259
s.name = sname
269260

270261
// Install the methods
@@ -283,7 +274,10 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) erro
283274
log.Print(str)
284275
return errors.New(str)
285276
}
286-
server.serviceMap[s.name] = s
277+
278+
if _, dup := server.serviceMap.LoadOrStore(sname, s); dup {
279+
return errors.New("rpc: service already defined: " + sname)
280+
}
287281
return nil
288282
}
289283

@@ -581,7 +575,7 @@ func (server *Server) readRequest(codec ServerCodec) (service *service, mtype *m
581575
return
582576
}
583577

584-
func (server *Server) readRequestHeader(codec ServerCodec) (service *service, mtype *methodType, req *Request, keepReading bool, err error) {
578+
func (server *Server) readRequestHeader(codec ServerCodec) (svc *service, mtype *methodType, req *Request, keepReading bool, err error) {
585579
// Grab the request header.
586580
req = server.getRequest()
587581
err = codec.ReadRequestHeader(req)
@@ -607,14 +601,13 @@ func (server *Server) readRequestHeader(codec ServerCodec) (service *service, mt
607601
methodName := req.ServiceMethod[dot+1:]
608602

609603
// Look up the request.
610-
server.mu.RLock()
611-
service = server.serviceMap[serviceName]
612-
server.mu.RUnlock()
613-
if service == nil {
604+
svci, ok := server.serviceMap.Load(serviceName)
605+
if !ok {
614606
err = errors.New("rpc: can't find service " + req.ServiceMethod)
615607
return
616608
}
617-
mtype = service.method[methodName]
609+
svc = svci.(*service)
610+
mtype = svc.method[methodName]
618611
if mtype == nil {
619612
err = errors.New("rpc: can't find method " + req.ServiceMethod)
620613
}

0 commit comments

Comments
 (0)