2015-04-20 69 views
1

出於好奇,我編寫了一些比較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'); 

注意,去實現有一對夫婦的未成年人的潛在性能的邊緣:

  1. Go將整數直接映射到整數,而JavaScript將轉換int埃格爾鍵字符串屬性名稱。

  2. 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中獲得的非常高的性能與運行時對於其鍵是連續整數的對象(例如,通過替換數組實現而不是散列表)相關的特定優化相關。

我投票關閉,因爲有可能沒有在這裏看到...

+0

我不確定Go不是哈希數字,我不確定JavaScript是否也是如此。 0 ... 1M之間的連續整數映射基本上是一個數組。將m初始化爲1M ints數組,將執行時間減少到2ms。現在用字符串做這個基準,這是一個真正的比較。如果v8的速度會更快,我也不會感到驚訝。 –

+0

@Not_a_Golfer:雅我有點猜測,可能會直接使用int鍵而不是散列它們;我想我可以閱讀哈希表實現來找出答案。有趣的是,如果我在兩種語言中都使用字符串鍵(使用s:= strconv.Itoa(i)'和'var s =''+ i'),那麼它們的表現大致相同;儘管在js中使用數字鍵仍然快得多。這裏有很多謎團...... – maerics

+0

「* JavaScript會將整數鍵轉換爲字符串屬性名稱。*」 - 否則不會。即使它們是相同的,那也不是發動機的功能。它很快意識到你正在濫用一個數組的對象,並將使用下面的數組。 – Bergi

回答

4

你的基準是合成了一下,就像任何基準測試。只是好奇的嘗試

for i := 0; i < 1000000; i += 9 { 

在執行。你可能會感到驚訝。

+0

嗯,是的,有趣。用其他方法增加似乎可以擊敗我懷疑逐個增加的v8優化(例如,使用數組實現而不是散列表)。 – maerics

+0

Go map是以散列表的形式實現的(不以任何方式排列數組),並通過一個只增加一個鍵值的方法來增加鍵值。 – Uvelichitel