Android SHA1 非常缓慢

4

我是否做错了什么,还是Android的JVM实现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),处理速度约为12兆/秒。当我在2.2(HTC Legend)上尝试时,速度甚至比第一个设备还要慢。难道从2.3开始发生了一些变化吗?


1
将日志记录移出循环并重新测试。 - Markus Kull
以一种方式实现了日志记录,当兆字节发生变化时打印消息 - 结果相同(120kb /秒) - lstipakov
对读取时间和哈希时间进行基准测试时,您可能会花费比您想象的更长时间来阅读。另外,尝试使用不同的缓冲区大小进行实验,增加缓冲区大小可能会有很大帮助。8k 块可能比您的卡上的文件系统块要小。 - Bruno Rohée
添加了traceview结果。我已经尝试过缓冲区大小-没有显著的差异。 - lstipakov
在iOS上,我能够接近每秒10m个哈希,在SHA256环境下...而在使用三星Galaxy S5时,我只能看到大约每秒150k个哈希。说实话,iOS和Android之间的性能差异令人尴尬。 - Albert Renshaw
1个回答

4
根据我的基准测试,该代码应该能够轻松达到超过120 kb/s的性能(我在不同的硬件上运行,但仍然如此)。
如果您使用Traceview对代码进行分析,时间花费在哪里?如果瓶颈是FileInputStream.read(),请考虑:
- 是否有其他应用程序与您同时使用sdcard,例如媒体索引应用程序等。与其他应用程序共享带宽会对您的应用程序的sdcard读取性能产生不利影响。 - 如果sdcard本身存在问题。尝试另一个sdcard或重新格式化您拥有的那个。
如果瓶颈是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上显然不是。

因此,对于您最初的问题,答案是:在Android 2.2中,由于Java实现,速度非常慢,但在Android 2.3中,由于本地代码的实现,速度显著提高。如果您在本地代码中使用自己的SHA-1实现,则应在Android 2.2上看到类似的加速效果。


我已经添加了跟踪结果。看起来瓶颈在update()函数中。 - lstipakov
我该如何使用android.security包?它似乎不是公共API的一部分。 - lstipakov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接