ここでは2つのことが機能しています。1つ目は、GoがマシンコードにコンパイルされてCPUで直接実行されるのに対し、Pythonは(特に低速の)VMに対してバイトコードで実行されるようにコンパイルされることです。
パフォーマンスに影響を与える2番目の、そしてより重要なことは、2つのプログラムのセマンティクスが実際には大幅に異なることです。Goバージョンでは、「x」と呼ばれる「ボックス」が作成されます。このボックスには、プログラムを通過するたびに数値が1ずつ増加します。Pythonバージョンは、実際には各サイクルで新しい「ボックス」(intオブジェクト)を作成する必要があります(そして、最終的にはそれらを破棄する必要があります)。プログラムを少し変更することで、これを実証できます。
package main
import (
"fmt"
)
func main() {
for i := 0; i < 10; i++ {
fmt.Printf("%d %p\n", i, &i)
}
}
...と:
x = 0;
while x < 10:
x += 1
print x, id(x)
これは、GoがCのルートであるため、場所を参照するために変数名を使用し、Pythonが物事を参照するために変数名を使用するためです。整数はPythonで一意の不変のエンティティと見なされるため、常に新しいエンティティを作成する必要があります。PythonはGoよりも遅いはずですが、最悪のシナリオを選択しました。ベンチマークゲームでは、平均して約25倍(最悪の場合は100倍)高速であることがわかります。
Pythonプログラムが遅すぎる場合は、Cに移動することで速度を上げることができます。幸い、この場合、誰かがすでにこれを行っています。空のループを次のようにxrange()を使用するように書き直す場合:
for x in xrange(1000000000):
pass
print "Done."
...約2倍の速度で実行されます。ループカウンターが実際にプログラムの主要なボトルネックであることがわかった場合は、問題を解決するための新しい方法を調査する時期かもしれません。