在对安全 框架 进行编码时,我经常遇到两难的问题:“ 合并还是不合并”
基本上,这个问题分为两个“组”:
第1组:SecureRandom因为对的调用nextBytes(...)是同步的,并且可能成为WebApp /多线程应用程序的瓶颈
SecureRandom
nextBytes(...)
第2组:加密服务提供商,如MessageDigest,Signature,Cipher,KeyFactory,…(因为成本的getInstance()?)
MessageDigest
Signature
Cipher
KeyFactory
getInstance()
你有什么意见 ?
您对这些问题有什么习惯?
我终于花了一些时间独自测试@Qwerky Share类,我发现结果相当……令人惊讶。
Share
该类缺少我的主要关注:GenericObjectPool或StackObjectPool之类的池。
因此,我对课程进行了重新设计,以测试所有4种选择:
由于1M在池中花费了太多时间,因此我不得不将循环数降低到100000。
我还在Thread.yield()每个循环的末尾添加了一个,以使负载具有更好的形状。
Thread.yield()
结果(累计运行时间):
对于MessageDigest和KeyFactory而言,池是性能的杀手,甚至比具有同步瓶颈的单个实例还要糟糕,而对于SecureRandom和Cipher来说,它们确实非常有用
如果让100个线程访问一个共享,MessageDigest并让它们分别计算1,000,000个哈希,则在我的计算机上,第一个线程完成70,160ms,最后一个完成98,748ms。
如果线程MessageDigest每次都创建一个新实例,那么第一个线程将在43,392ms内完成,最后一个58,691ms。
编辑: 实际上,在此示例中,只有两个线程,该示例创建新实例的运行速度更快。
import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Share { final byte[] bytes = new byte[100]; final MessageDigest sharedDigest; final ExecutorService pool; int threads = 100; Share() throws NoSuchAlgorithmException { sharedDigest = MessageDigest.getInstance("MD5"); pool = Executors.newFixedThreadPool(threads); } void go() { for (int i=0; i<threads; i++) { pool.execute(new Runnable() { public void run() { long start = System.currentTimeMillis(); for (int i=0; i<1000000; i++) { /* synchronized (sharedDigest) { sharedDigest.reset(); sharedDigest.update(bytes); sharedDigest.digest(); }*/ try { MessageDigest digest = MessageDigest.getInstance("MD5"); digest.reset(); digest.update(bytes); digest.digest(); } catch (Exception ex) { ex.printStackTrace(); } } long end = System.currentTimeMillis(); System.out.println(end-start); pool.shutdown(); } }); } } public static void main(String[] args) throws Exception { Share share = new Share(); share.go(); } }