gpt4 book ai didi

戈朗 : Why not the free list in rpc server reuse instance directly

转载 作者:IT王子 更新时间:2023-10-29 02:12:06 24 4
gpt4 key购买 nike

RPC server在 net/rpc 包中包含两个免费列表,用于 Request 结构和 Response 结构。 Request 结构通过其 next 字段维护此列表。

// Server represents an RPC Server.
type Server struct {
// ...
freeReq *Request // header node of Request free list
freeResp *Response // header node of Response free list
}

type Request struct {
ServiceMethod string // format: "Service.Method"
Seq uint64 // sequence number chosen by client
next *Request // for free list in Server
}

rpc server中的free list好像是一个对象池。在处理rpc 请求时,服务器调用getRequest 从空闲列表中获取一个请求实例。处理请求后,服务器调用freeRequest将请求实例放回空闲列表。

func (server *Server) getRequest() *Request {
server.reqLock.Lock()
req := server.freeReq
if req == nil {
req = new(Request) // free list is empty
} else {
server.freeReq = req.next // free list isn't empty
*req = Request{} // Why not reuse instance directly?
}
server.reqLock.Unlock()
return req
}

func (server *Server) freeRequest(req *Request) {
server.reqLock.Lock()
req.next = server.freeReq
server.freeReq = req
server.reqLock.Unlock()
}

我对 getRequest 函数感到困惑。当空闲列表为空时,它会按预期创建一个新实例。当空闲列表不为空时,它会执行 *req = Request{}。我认为 Request{} 也创建了一个新实例。那么持有这个空闲列表有什么意义呢?


另外,我写了一个demo来展示*req = Request{}格式语句的效果。

type Student struct {
Name string
Age int
}

func main() {
s := &Student{"John", 20}
fmt.Printf("Address: %p Content: %v\n", s, s)

*s = Student{"Frank", 18} // similar to *req = Request{}
fmt.Printf("Address: %p Content: %v\n", s, s)
}

输出是:

Address: 0xc42000a4c0 Content: &{John 20}
Address: 0xc42000a4c0 Content: &{Frank 18}

所以语句 *req = Request{} 不会改变指针的地址,但会改变内容。

最佳答案

freelist 的想法是通过重用已经创建的对象实例来减少动态内存分配的数量。

它是这样工作的:

当第一个请求发出时,空闲列表是空的,因此将在堆上分配一个新的结构。当不再需要这些时,它们将被放入空闲列表以供重用。如果您没有空闲列表,那么下一个请求将需要在堆上创建新的请求/响应结构,一遍又一遍地这样做可能代价高昂。使用空闲列表可以避免这种情况,因为下一个请求可以简单地重用已经分配(和停放)的对象。

我猜你对这一行感到困惑:

*req = Request{}

与 freelist 为空并使用 req = new(Request) 在堆上创建新对象的情况相反,这不会在堆上分配对象。

它只是通过复制默认值将已经分配的对象(从空闲列表中取出)重置为默认状态。

您可以将该行分解为以下内容:

r := Request{} // Create a request with default content on stack (not heap!)
*req = r // Copy all fields from default request to req

无论在 getRequest() 中采用什么路径,它总是返回一个默认的初始化请求对象 - 没有前一个请求的遗留物。

关于戈朗 : Why not the free list in rpc server reuse instance directly,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43345097/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com