在编写安全框架时,我面临着一个常见的困境:"汇集或不汇集"
基本上这个问题分为两个"群体":
第1组:SecureRandom
因为调用nextBytes(...)
是同步的,它可能成为WebApp /多线程应用程序的瓶颈
第2组:加密服务提供商,如MessageDigest
,Signature
,Cipher
,KeyFactory
,...(因为的成本getInstance()
?)
你有什么意见 ?
你在这些问题上的习惯是什么?
我终于花时间自己测试了@Qwerky Share
课程,我觉得结果很......令人惊讶.
这个类缺乏我的主要关注:像GenericObjectPool或StackObjectPool这样的池.
所以我重新修改了这个类以测试所有4种选择:
我不得不将循环次数降低到100000,因为1M花了太多时间在游泳池上.
我还在Thread.yield()
每个循环的末尾添加了一个,以使负载具有更好的形状.
结果(累积运行时):
对于MessageDigest和KeyFactory,池是执行器杀手,甚至比具有同步瓶颈的单个实例更糟糕,而它们在SecureRandom和Cipher方面非常有用
如果您给100个线程访问共享MessageDigest
并让它们计算1,000,000个哈希值,那么在我的机器上第一个线程完成70,160毫秒,最后一个完成98,748毫秒.
如果线程MessageDigest
每次创建一个新实例,则第一个线程在43,492ms完成,最后一个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();
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1952 次 |
最近记录: |