Golang Go语言中结构体作为函数参数/返回值无脑指针效率反而低下?
最近看到一篇文章
https://segment.com/blog/allocation-efficiency-in-high-performance-go-services/
里面关于指针提到了一点
Copying objects within a cache line is the roughly equivalent to copying a single pointer.
CPUs move memory between caching layers and main memory on cache lines of constant size. On x86 this is 64 bytes.
Further, Go uses a technique called Duff ’ s device to make common memory operations like copies very efficient.
大致意思是现代 CPU 从缓存和主存储器之间移动数据存在一个固定的尺寸,即使使用指针也最少会产生这个尺寸的交换.所以函数参数如果是一个不大的结构,使用指针还是拷贝原变量并没有很大的区别.
再加上使用指针的话会导致 Go 把变量逃逸到堆而不是分配在栈上,结果是函数参数使用指针反而效率不如使用拷贝.
看完之后对我之前几乎无脑传入 /返回指针的代码方式产生了很大的 shock
想问一下有关于 CPU 这块策略的学习资料嘛?
Golang Go语言中结构体作为函数参数/返回值无脑指针效率反而低下?
更多关于Golang Go语言中结构体作为函数参数/返回值无脑指针效率反而低下?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Intel® 64 and IA-32 Architectures Software Developer Manuals
你会震惊的
emmmmm…其实最后一句话我斟酌过采用的"学习资料"而不是"文档",这种官方的文档实在是啃不动哎…
面向 cpu cache 优化,lz 大概需要去补一下组成
CPU 寻址时会从缓存中查找,从一级缓存到二级缓存等,而 CPU 缓存被分割为多个 cache line,cache line 是缓存中最小的单元,寻址时会从内存中将 cache line 大小的内存数据拷贝到 CPU 缓存,再传送到寄存器,应该是这样。
在Go语言中,关于结构体作为函数参数或返回值时是否应无脑使用指针,确实存在一些常见的误解。首先,要明确的是,是否使用指针传递结构体并非单纯基于效率考虑,而应根据具体场景和需求来决定。
使用指针传递结构体确实可以减少内存拷贝,这在结构体较大或函数需要修改结构体内部数据时很有用。然而,如果结构体较小且不需要修改,直接传递值可能更为简单和直观,且在现代处理器和编译器优化下,性能差异可能并不显著。
此外,无脑使用指针可能会引入额外的复杂性和错误风险,如空指针解引用、内存泄漏等。因此,在决定使用指针还是值时,应综合考虑代码的可读性、可维护性和实际性能需求。
总的来说,Go语言的设计哲学鼓励简洁和直接,这通常意味着在可能的情况下优先使用值传递。然而,在特定情况下,如处理大型数据结构或需要修改数据时,使用指针传递是更合适的选择。
因此,对于“结构体作为函数参数/返回值无脑指针效率反而低下”的观点,不能一概而论。正确的做法是根据具体场景和需求进行权衡和选择,以实现代码的简洁性、可读性和高效性的平衡。