关于go中拷贝次数进而影响性能的问题

先来看这么一个例子:

var aMap =map[int]int
aMap[1]=1

tmp:=aMap[1]
testMap1(tmp)
testMap2(aMap[1])

假设testMap1和testMap2的功能都是拿到参数之后打印一下参数值,那么到在他们打印前,testMap1完成这个动作进行了两次拷贝,第一次拷贝是tmp:=aMap[1],第二次拷贝是tmp到参数值。testMap2只需要一次拷贝。那么单从代码性能来看,肯定不应该用tmp:=aMap[1]这种方式去调用testMap。

那么我们再看go1.9中的sync.Map,我需要获取map中的value需要调用其Load方法,那么这肯定会产生一次拷贝 即 tmp,_:=syncmap.Load(key),而如果不用sync.Map,用普通Map,就可以像上面那样直接 map[key]取出来用,这样就少了一次拷贝。

不知道我这样想的对不对,碰到value是那种很大的struct,拷贝的开销应该不小吧,有没有什么好的解决这个拷贝开销的思路,如果用sync.Map的话

已邀请:

Xargin

赞同来自: ddxx11223 ianwoolf

和 tao 师傅说的一样,这种问题没必要纠结,看看优化后的汇编:

** 9        testMap(aMap[1])

    0x104fa47 <+135>: mov    qword ptr [rsp], rax
    0x104fa4b <+139>: mov    rax, qword ptr [rsp + 0x30]
    0x104fa50 <+144>: mov    qword ptr [rsp + 0x8], rax
    0x104fa55 <+149>: mov    qword ptr [rsp + 0x10], 0x1
    0x104fa5e <+158>: call   0x1008eb0                 ; runtime.mapaccess1_fast64 at hashmap_fast.go:110
    0x104fa63 <+163>: mov    rax, qword ptr [rsp + 0x18]
    0x104fa68 <+168>: mov    rax, qword ptr [rax]
    0x104fa6b <+171>: mov    qword ptr [rsp + 0x28], rax
** 9        tmp := aMap[1]
   10       testMap(tmp)

    0x104fa47 <+135>: mov    qword ptr [rsp], rax
    0x104fa4b <+139>: mov    rax, qword ptr [rsp + 0x30]
    0x104fa50 <+144>: mov    qword ptr [rsp + 0x8], rax
    0x104fa55 <+149>: mov    qword ptr [rsp + 0x10], 0x1
    0x104fa5e <+158>: call   0x1008eb0                 ; runtime.mapaccess1_fast64 at hashmap_fast.go:110
    0x104fa63 <+163>: mov    rax, qword ptr [rsp + 0x18]
    0x104fa68 <+168>: mov    rax, qword ptr [rax]
    0x104fa6b <+171>: mov    qword ptr [rsp + 0x28], rax

两者完全一致,连地址都没差。

c1.go:
package main

func testMap(a int) {
    println(a)
}

func main() {
    var aMap = map[int]int{1: 1}
    tmp := aMap[1]
    testMap(tmp)
}

c2.go:
package main

func testMap(a int) {
    println(a)
}

func main() {
    var aMap = map[int]int{1: 1}
    testMap(aMap[1])
}

simple - 既要有梦想,又要有实力

赞同来自: ddxx11223

像list/stack/queue/set/map等数据容器中存储的数据是在存储在堆上的,所以我觉得两种方式都copy了两次,第一次从堆上copy到栈上,第二次copy到调用的函数栈里面。

如果要存储的数据元素本身很大,一般不会直接将值本身存储到数据容器中,而是存储数据元素的指针或引用,不然读写性能会受到一定的影响。

taowen

赞同来自: ddxx11223

编译器会优化成一样的吧。你考虑多了。

要回复问题请先登录注册