我注意到在对
快速方式:
编辑:在本地运行时,差异较小,但仍然存在。
编辑2:建议我转储了机器代码。以下是相关片段。
对于x[0]++:
map[int]int
变量的两个增量方法中,存在3倍速度因子:快速方式:
myMap[key]++
慢速方式:myMap[key]=myMap[key]+1
这可能并不令人惊讶,因为至少从表面上看,在第二种情况下,我指示Go两次访问myMap。 我只是好奇:熟悉Go编译器的任何人能帮助我理解地图上这些操作之间的差异吗? 有了如何编译器工作的知识,是否有更快的技巧来增加地图?编辑:在本地运行时,差异较小,但仍然存在。
package main
import (
"fmt"
"math"
"time"
)
func main() {
x, y := make(map[int]int), make(map[int]int)
x[0], y[0] = 0, 0
steps := int(math.Pow(10, 9))
start1 := time.Now()
for i := 0; i < steps; i++ {
x[0]++
}
elapsed1 := time.Since(start1)
fmt.Println("++ took", elapsed1)
start2 := time.Now()
for i := 0; i < steps; i++ {
y[0] = y[0] + 1
}
elapsed2 := time.Since(start2)
fmt.Println("y=y+1 took", elapsed2)
}
输出:
++ took 8.1739809s
y=y+1 took 17.9079386s
编辑2:建议我转储了机器代码。以下是相关片段。
对于x[0]++:
0x4981e3 488d05b6830100 LEAQ runtime.types+95648(SB), AX
0x4981ea 48890424 MOVQ AX, 0(SP)
0x4981ee 488d8c2400020000 LEAQ 0x200(SP), CX
0x4981f6 48894c2408 MOVQ CX, 0x8(SP)
0x4981fb 48c744241000000000 MOVQ $0x0, 0x10(SP)
0x498204 e8976df7ff CALL runtime.mapassign_fast64(SB)
0x498209 488b442418 MOVQ 0x18(SP), AX
0x49820e 48ff00 INCQ 0(AX)
对于 y[0] = y[0] + 1
0x498302 488d0597820100 LEAQ runtime.types+95648(SB), AX
0x498309 48890424 MOVQ AX, 0(SP)
0x49830d 488d8c24d0010000 LEAQ 0x1d0(SP), CX
0x498315 48894c2408 MOVQ CX, 0x8(SP)
0x49831a 48c744241000000000 MOVQ $0x0, 0x10(SP)
0x498323 e80869f7ff CALL runtime.mapaccess1_fast64(SB)
0x498328 488b442418 MOVQ 0x18(SP), AX
0x49832d 488b00 MOVQ 0(AX), AX
0x498330 4889442448 MOVQ AX, 0x48(SP)
0x498335 488d0d64820100 LEAQ runtime.types+95648(SB), CX
0x49833c 48890c24 MOVQ CX, 0(SP)
0x498340 488d9424d0010000 LEAQ 0x1d0(SP), DX
0x498348 4889542408 MOVQ DX, 0x8(SP)
0x49834d 48c744241000000000 MOVQ $0x0, 0x10(SP)
0x498356 e8456cf7ff CALL runtime.mapassign_fast64(SB)
0x49835b 488b442418 MOVQ 0x18(SP), AX
0x498360 488b4c2448 MOVQ 0x48(SP), CX
0x498365 48ffc1 INCQ CX
0x498368 488908 MOVQ CX, 0(AX)
奇怪的是,++甚至不调用map访问! ++显然比2或3个订单简单。 我的机器解析能力到此为止,如果有人了解情况,我很想听听。
go tool objdump
命令来查看生成的机器码,例如go tool objdump -S -s "main.main" ./example1
。 - dm03514go vet
不断提示我使用++
语句的原因。 - RickyA++花费了8.1739809秒
y=y+1花费了17.9079386秒
。我无法重现或理解你的结果。请查看我的答案获取真实结果:++花费了7.995184419秒
y=y+1花费了10.259916484秒
。” - peterSOgo version go1.11 windows/amd64
上运行了这个程序。现在我想起来了,我应该在 Linux 上检查一下是否相同。这可能会解释为什么我的 y=y+1 和 @perterSO 报告的结果相差6秒。 - kapaw