我的应用程序使用sync.Map来存储打开的套接字连接,这些连接可以通过多个goroutines并发访问。
我想知道是将这些连接存储为structs net.Conn还是作为references *net.Conn存储。
这两种选择的好处/缺点是什么,优先的解决方案是什么?
发布于 2022-01-18 12:22:30
虽然@blackgreen是正确的,但我会对推理做一些扩展。
sync.Map类型被显式定义为在interface{}上操作。
现在请记住,在Go中,接口不仅仅是类型系统使用的抽象;相反,您可以拥有接口类型的值,而这些值的内存中表示形式是包含两个指针的struct --用于描述存储在变量中的值的动态类型的内部对象,以及值本身(或运行时在堆上创建的值的副本)。
这意味着,如果要在sync.Map中存储指向任何内容的指针,则存储的任何此类指针都将转换为interface{}类型的值,并且在sync.Map中占据完全相同的空间。
如果您将net.Conn类型的值直接存储在那里,那么它们将直接存储--仅仅因为它们已经是接口值,所以Go将只复制这对指针。
从表面上看,这两种方法在所使用的空间上都是相同的,但我不同意。
若要将指向net.Conn值的指针存储在容器数据类型(如sync.Map )中,程序必须确保在堆上分配该值(而不是直接在当前运行的sync.Map的堆栈上分配该值),这一事实可能迫使编译器安排确保直接在堆上分配原始net.Conn值。
换句话说,存储指向接口类型变量的指针在内存使用方面可能会(而且通常也会--由于典型代码的组织方式)更加浪费。
此外,大多数反引用(指针追逐)倾向于破坏CPU缓存;这不是一个游戏改变器,但当您在紧循环中遍历集合时,可能会增加几个参数。
话虽如此,我还是建议您不要直接在像sync.Map这样的容器中丢弃存储指针:有时候它会派上用场--例如,为了将数组重用到片中,您通常会存储指向此类数组的第一个元素的指针。
https://stackoverflow.com/questions/70754495
复制相似问题