Go 如何正确使用sync.pool进行切片
我正在构建一个Go应用程序来服务数千个HTTP请求。服务包括解析输入、处理输入和返回输出 输入解析包括将Go 如何正确使用sync.pool进行切片,go,Go,我正在构建一个Go应用程序来服务数千个HTTP请求。服务包括解析输入、处理输入和返回输出 输入解析包括将json解析为map[string]string 如何实现此解析的内存池 最小可复制示例: var poolTest *sync.Pool func init() { poolTest = &sync.Pool{ New: func() interface{} { return new([]map[string]string)
json
解析为map[string]string
如何实现此解析的内存池
最小可复制示例:
var poolTest *sync.Pool
func init() {
poolTest = &sync.Pool{
New: func() interface{} {
return new([]map[string]string)
},
}
}
func Requesthandler (ctx *fasthttp.RequestCtx) {
poolTestList := poolTest.Get().(*[]map[string]string)
input := ctx.PostBody()
_=json.Unmarshal(input, poolTestList)
//do something
print(*(poolTestList))
//clear and return to pool
(*poolTestList) = (*poolTestList)[:0]
poolTest.Put(poolTestList)
}
func main() {
_ = (&fasthttp.Server{
Handler: Requesthandler,
ReadBufferSize: 8192,
TCPKeepalive: true,
}).ListenAndServe(":3000")
}
我感到困惑的部分是清理和返回游泳池
这是正确的方法吗?您的实现通常是正确的,但是这里有一些奇怪的事情。首先,几乎不需要指向切片的指针;你在这里绝对不需要。您的值应该只是
[]映射[string]字符串
而不是*[]映射[string]字符串
其次,最佳实践是在Get
之后重置池对象,而不是在Put
之前。这是最安全的,因为这意味着Get
不会对从池中接收到的值做出任何潜在的不安全假设。如果项目倾向于在池中停留很长时间并且非常大,您也可以同时执行这两种操作(这里可能会有来自地图切片的非常高的内存使用率,因此这将取决于您的用例)
需要注意的是,//do something
中的内容可能是相关的,因为这里使用的是映射和切片,它们的行为符合引用语义。如果任何切片或映射泄漏了此方法,您可能会在无意中遇到一些潜在问题,这些问题可能很难诊断
最后,请记住,这段代码并不是汇集贴图,而是汇集切片。因此,如果这些是大型地图的短列表,那么这里的好处可能很小。事实上,即使是长长的地图列表,也可能很少。我将删除池代码、基准和配置文件,并确保您确实在优化与性能相关的内容。您正在将
**[]映射[string]字符串
传递到解组
,这可能不是您想要的。片分配可能不是这里的瓶颈——您已经分配了许多片,甚至可以深入到http请求中,所有数据都将在映射中,使用新分配的结构。你确定sync.Pool
对你有任何好处吗?这根本是错误的。以正确的代码开始。如果GC压力是实际瓶颈,则进行优化。重用没有映射的切片是毫无意义的,重用map memmory是很困难的。如果GC压力是你的问题:实现你自己的json.unmarshalery你知道“数千个请求”对任何现代计算机来说都不算什么,对吗?(除非你是指每秒)这看起来很像过早优化。