更新:2009-05-29
感谢所有的建议和建议。 我使用您的建议使我的生产代码的平均执行速度比几天前的最佳结果快 2.5 倍。 最后,我能够使 java 代码最快。
教训:
我下面的示例代码显示了原始整数的插入,但生产代码实际上是存储字符串(我的错)。当我更正 python 执行时间从 2.8 秒变为 9.6 时。所以马上,java 在存储对象时实际上更快。
但它并不止于此。我一直在执行java程序,如下所示:
java -Xmx1024m 速度测试
但是,如果您将初始堆大小设置如下,您将获得巨大的改进:
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代码做的事情基本上是一样的。但它在 8.3 秒而不是 3.3 秒内执行。
我从一个真实的例子中提取了这个简单的例子来简化事情。关键元素是我有(set 或 hashSet)最终有很多成员,就像这个例子一样。
以下是我的问题:
为什么我的 python 实现比我的 java 实现快?
有没有比 hashSet (java) 更好的数据结构来保存唯一的集合?
什么会使 python 实现更快?
什么会使java实现更快?
更新:
感谢所有迄今为止做出贡献的人。请允许我添加一些细节。
我没有包含我的生产代码,因为它非常复杂。并且会产生很多干扰。我上面介绍的案例是最简单的。我的意思是java put调用似乎比python set`s add()慢得多。
生产代码的 java 实现也比 python 版本慢 2.5 - 3 倍——就像上面一样。
我不关心 vm 预热或启动开销。我只想比较从我的 startTime 到我的 totalTime 的代码。请不要为其他事情操心。
我用足够多的桶初始化了哈希集,这样它就不必重新哈希了。(我总是会提前知道集合最终将包含多少元素。)我想有人可能会争辩说我应该将它初始化为迭代次数/0.75。但是,如果您尝试一下,您会发现执行时间并没有受到显着影响。
我为那些好奇的人设置了 Xmx1024m(我的机器有 4GB 的内存)。
我正在使用 java 版本:Java(TM) SE Runtime Environment (build 1.6.0_13-b03)。
在生产版本中,我在 hashSet 中存储了一个字符串(2-15 个字符),因此我不能使用原语,尽管这是一个有趣的案例。
我已经多次运行代码。我非常相信 python 代码比 java 代码快 2.5 到 3 倍。