Golang vs JavaScript(v8/node.js)映射性能

mae*_*ics 2 javascript performance dictionary go data-structures

出于好奇,我写了一些琐碎的基准测试,将golang地图的性能与用作地图的JavaScript(v8/node.js)对象进行比较,并对其相对性能感到惊讶.JavaScript对象的执行速度大约是go map的两倍(甚至包括一些较小的性能边缘)!

这是go实现:

// map.go
package main
import "fmt"
import "time"
func elapsedMillis(t0, t1 time.Time) float64 {
  n0, n1 := float64(t0.UnixNano()), float64(t1.UnixNano())
  return (n1 - n0) / 1e6
}
func main() {
  m := make(map[int]int, 1000000)
  t0 := time.Now()
  for i := 0; i < 1000000; i++ {
    m[i] = i     // Put.
    _ = m[i] + 1 // Get, use, discard.
  }
  t1 := time.Now()
  fmt.Printf("go: %fms\n", elapsedMillis(t0, t1))
}
Run Code Online (Sandbox Code Playgroud)

这是JavaScript:

#!/usr/bin/env node
// map.js
function elapsedMillis(hrtime0, hrtime1) {
  var n0 = hrtime0[0] * 1e9 + hrtime0[1];
  var n1 = hrtime1[0] * 1e9 + hrtime1[1];
  return (n1 - n0) / 1e6;
}
var m = {};
var t0 = process.hrtime();
for (var i=0; i<1000000; i++) {
  m[i] = i; // Put.
  var _ = m[i] + 1; // Get, use, discard.
}
var t1 = process.hrtime();
console.log('js: ' + elapsedMillis(t0, t1) + 'ms');
Run Code Online (Sandbox Code Playgroud)

请注意,go实现具有以下几个潜在的性能优势:

  1. Go将整数直接映射到整数,而JavaScript会将整数键转换为字符串属性名称.

  2. Go使其地图的初始容量等于基准大小,而JavaScript正从其默认容量增长).

但是,尽管上面列出了潜在的性能优势,但是go map使用似乎只能执行JavaScript对象映射的一半!例如(代表):

go: 128.318976ms
js: 48.18517ms
Run Code Online (Sandbox Code Playgroud)

我在做地图或以某种方式比较苹果和橙子时做了一些明显错误的事情吗?

我本来希望go map至少也能执行 - 如果不比JavaScript对象更好,就像map一样.这只是go的不成熟的标志(darwin/amd64上的1.4)还是它代表了我缺少的两种语言数据结构之间的一些根本区别?

[更新]

请注意,如果您明确使用字符串键(例如分别通过s := strconv.Itoa(i)var s = ''+i在Go和JavaScript中),那么它们的性能大致相当.

我的猜测是,v8的非常高的性能与该运行时针对其键是连续整数的对象的特定优化有关(例如,通过替换数组实现而不是哈希表).

我投票结束,因为这里可能没有什么可看的......

Uve*_*tel 5

您的基准测试是合成的,就像任何基准测试一样.只是为了好奇的尝试

for i := 0; i < 1000000; i += 9 {
Run Code Online (Sandbox Code Playgroud)

在Go实施中.你可能会感到惊讶.

  • 所以你的建议是在 JS 中执行 **所有** 循环步骤,但让 Go 跳过 89% 的迭代并对其进行基准测试?非常有趣的方法,具有非常“令人惊讶”的结果:D (4认同)