出於好奇,我編寫了一些比較Golang地圖和JavaScript(v8/node.js)對象的性能的微不足道的基準,這些對象用作地圖,並且對它們的相對性能感到驚訝。 JavaScript對象的執行速度大約是地圖的兩倍(甚至包括一些次要的性能邊緣)!Golang vs JavaScript(v8/node.js)地圖性能
這裏是去實現:
// 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))
}
這裏是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');
注意,去實現有一對夫婦的未成年人的潛在性能的邊緣:
Go將整數直接映射到整數,而JavaScript將轉換int埃格爾鍵字符串屬性名稱。
Go以其初始容量等於基準大小的方式繪製其地圖,而JavaScript則從其默認容量增加)。
但是,儘管上面列出了潛在的性能優勢,但go map的使用似乎以JavaScript對象圖的一半左右執行!例如(代表):
go: 128.318976ms
js: 48.18517ms
我在做一些明顯錯誤的地圖或以某種方式比較蘋果橙子?
我會期望地圖至少能夠執行 - 如果不是比JavaScript對象更好的地圖。這只是一個走向不成熟的標誌(darwin/amd64上的1.4)還是它代表了我缺少的兩種語言數據結構之間的一些根本區別?
[更新]
請注意,如果您明確使用字符串鍵(例如,通過s := strconv.Itoa(i)
和圍棋和JavaScript var s = ''+i
,分別),那麼它們的性能大致等同。
我的猜測是,從v8中獲得的非常高的性能與運行時對於其鍵是連續整數的對象(例如,通過替換數組實現而不是散列表)相關的特定優化相關。
我投票關閉,因爲有可能沒有在這裏看到...
我不確定Go不是哈希數字,我不確定JavaScript是否也是如此。 0 ... 1M之間的連續整數映射基本上是一個數組。將m初始化爲1M ints數組,將執行時間減少到2ms。現在用字符串做這個基準,這是一個真正的比較。如果v8的速度會更快,我也不會感到驚訝。 –
@Not_a_Golfer:雅我有點猜測,可能會直接使用int鍵而不是散列它們;我想我可以閱讀哈希表實現來找出答案。有趣的是,如果我在兩種語言中都使用字符串鍵(使用s:= strconv.Itoa(i)'和'var s =''+ i'),那麼它們的表現大致相同;儘管在js中使用數字鍵仍然快得多。這裏有很多謎團...... – maerics
「* JavaScript會將整數鍵轉換爲字符串屬性名稱。*」 - 否則不會。即使它們是相同的,那也不是發動機的功能。它很快意識到你正在濫用一個數組的對象,並將使用下面的數組。 – Bergi