mirror of https://github.com/golang/go.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 <bcmills@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
d6ce7e4fec
commit
ce5263ff8d
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue