2011-10-31 74 views
3

我做错了,或者Android的JVM实现SHA1是痛苦的慢?我的代码如下:Android的SHA1是痛苦的缓慢

in = new FileInputStream("/mnt/sdcard/200mb"); 
MessageDigest digester = MessageDigest.getInstance("sha1"); 
byte[] bytes = new byte[8192]; 
int byteCount; 
int total = 0; 
while ((byteCount = in.read(bytes)) > 0) { 
    total += byteCount; 
    digester.update(bytes, 0, byteCount); 
    Log.d("sha", "processed " + total); 
}  

这里是日志:

10-31 13:59:53.790 D/sha  (3386): processed 4931584 
10-31 13:59:54.790 D/sha  (3386): processed 5054464 
10-31 13:59:55.780 D/sha  (3386): processed 5177344 

大约是100K /秒,对我来说是不能接受的。

我正在使用物理设备(LG P990,2.2.2)。我能用Java获得更好的结果吗,还是必须查看JNI实现?

我玩过缓冲区大小 - 没有显着差异。

Traceview结果

所以它似乎是更新散列的瓶颈。

enter image description here

研究

这很有趣。当我尝试2.3.2(SE Xperia)时,处理速度约为12meg/sec。当我尝试2.2(HTC Legend)时,速度比第一个设备还要慢。从2.3开始有什么变化吗?

+1

将注销移出循环并再次测试 –

+0

以兆字节发生更改时打印消息的方式实施日志记录 - 结果相同(120kb/sec) – lstipakov

+0

基准测试什么是读取时间和什么是散列时间,您可能会花费更多的时间阅读,你认为你是。还可以尝试使用不同的缓冲区大小,增加它可以帮助很多,8k块可能比卡上的文件系统块小。 –

回答

3

根据我的基准测试,该代码应该能够轻松地执行比120 kb/s更好的方式(我在不同的硬件上运行,但仍然)。

如果您使用Traceview来分析代码,那么花在哪里?如果瓶颈是FileInputStream.read(),想想:

  • 如果一些其他的应用程序使用的SD卡在同一时间,因为你,像一个媒体索引应用程序什么的。与其他应用程序共享带宽将对应用程序的SD卡阅读性能产生不利影响。
  • 如果SD卡本身就是问题。尝试另一个SD卡或重新格式化你的。

如果瓶颈是MessageDigest.update()(我怀疑),我想你需要研究一个JNI解决方案。对于您的信息,SHA-1实现已经在本机代码中(请参阅android_message_digest_sha1.cpp),但也许您可以通过避免某些本机< - > Java复制来获得加速。

更新1(请无视):

(根据您的分析,这个问题似乎是,你不使用Android的优化android.security.MessageDigest而是java.security.MessageDigest尝试android.security.MessageDigest,而不是同时在Android 2.2和2.3。具有android.security.MessageDigest天然SHA-1的实施方式)

更新2:

对不起,我忘android.security.MessageDigest是内部的。我现在意识到我还在使用java.security.MessageDigest进行基准测试。然而,我在Android 2.3上运行,事实证明Android 2.3中的java.security.MessageDigest的SHA-1实现也是在本机代码中,而Android 2.2上的情况并非如此。

因此,您原始问题的答案是:是的,由于Java实现,它在Android 2.2中速度很慢,但由于在本机代码中的实现,在Android 2.3中速度明显更快。如果您在本机代码中使用自己的SHA-1实现,则应该会在Android 2.2上看到类似的加速。

+0

我已添加追踪结果。看起来瓶颈在于update()。 – lstipakov

+0

谢谢。请参阅最新的答案。 –

+0

如何使用android.security包?它似乎不属于公共API。 – lstipakov