更新: 2009-05-29
すべての提案とアドバイスに感謝します。 私はあなたの提案を使用して、数日前の最高の結果よりも平均で 2.5 倍高速に実稼働コードを実行できるようにしました。 最終的にJavaコードを最速にすることができました。
教訓:
以下のコード例は、プリミティブ int の挿入を示していますが、製品コードは実際には文字列を格納しています (私の悪い点です)。Pythonの実行時間が2.8秒から9.6秒になったことを修正しました。そのため、オブジェクトを格納するときは、実際には Java の方が高速でした。
しかしそれだけではありません。次のようにJavaプログラムを実行していました。
Java -Xmx1024m SpeedTest
しかし、初期ヒープ サイズを次のように設定すると、大幅な改善が得られます。
java -Xms1024m -Xmx1024m SpeedTest
この単純な変更により、実行時間が 50% 以上短縮されました。したがって、SpeedTest の最終結果は python 9.6 秒です。Java 6.5 秒。
元の質問:
次のpythonコードがありました:
import time
import sys
def main(args):
iterations = 10000000
counts = set()
startTime = time.time();
for i in range(0, iterations):
counts.add(i)
totalTime = time.time() - startTime
print 'total time =',totalTime
print len(counts)
if __name__ == "__main__":
main(sys.argv)
私のマシンでは約 3.3 秒で実行されましたが、もっと速くしたかったので、Java でプログラムすることにしました。Java はコンパイルされており、一般に Python よりも高速であると考えられているため、大きな見返りが得られると思いました。
Javaコードは次のとおりです。
import java.util.*;
class SpeedTest
{
public static void main(String[] args)
{
long startTime;
long totalTime;
int iterations = 10000000;
HashSet counts = new HashSet((2*iterations), 0.75f);
startTime = System.currentTimeMillis();
for(int i=0; i<iterations; i++)
{
counts.add(i);
}
totalTime = System.currentTimeMillis() - startTime;
System.out.println("TOTAL TIME = "+( totalTime/1000f) );
System.out.println(counts.size());
}
}
したがって、この Java コードは基本的に Python コードと同じことを行います。しかし、3.3 秒ではなく 8.3 秒で実行されました。
単純化するために、この単純な例を実際の例から抽出しました。重要な要素は、例のように多くのメンバーで終わる (set または hashSet) があることです。
ここに私の質問があります:
Python の実装が Java の実装よりも速いのはなぜですか?
一意のコレクションを保持するために、hashSet (java) よりも優れたデータ構造はありますか?
Python の実装を高速化するにはどうすればよいでしょうか?
Java の実装を高速化するにはどうすればよいでしょうか?
アップデート:
これまでに貢献してくれたすべての人に感謝します。詳細を追加させてください。
非常に複雑なため、本番コードは含めていません。そして、多くの気晴らしを生み出すでしょう。上記のケースは、可能な限り単純化したものです。つまり、java の put 呼び出しは、python set の add() よりもはるかに遅いようです。
本番コードの Java 実装も、上記と同様に、Python バージョンよりも約 2.5 ~ 3 倍遅くなります。
VM のウォームアップや起動時のオーバーヘッドは気にしません。startTime から totalTime までのコードを比較したいだけです。他のことは気にしないでください。
ハッシュセットを再ハッシュする必要がないように、十分な数のバケットを使用してハッシュセットを初期化しました。(コレクションに最終的に含まれる要素の数は常に前もってわかっています。) 私は、コレクションを iterations/0.75 に初期化するべきだったと主張することができると思います。しかし、試してみると、実行時間に大きな影響がないことがわかります。
好奇心旺盛な人のために Xmx1024m を設定しました (私のマシンには 4GB の RAM があります)。
Java バージョン: Java(TM) SE ランタイム環境 (ビルド 1.6.0_13-b03) を使用しています。
のプロダクション バージョンでは、hashSet に文字列 (2 ~ 15 文字) を格納しているため、プリミティブを使用できませんが、これは興味深いケースです。
コードを何度も実行しました。私は、Python コードが Java コードよりも 2.5 倍から 3 倍高速であることを確信しています。