解决方案
- MessageDigest => 根据需要创建新的实例
- KeyFactory => 使用单个共享实例
- SecureRandom => 使用 StackObjectPool
- Cipher => 使用 StackObjectPool
问题
在编写安全框架时,我经常面临一个困境:"使用池还是不使用池"
基本上,这个问题可以分为两个“组”:
第一组:使用
SecureRandom
,因为调用nextBytes(...)
是同步的,可能会成为 WebApp/多线程应用程序的瓶颈。第二组:加密服务提供者,例如
MessageDigest
、Signature
、Cipher
、KeyFactory
等(因为getInstance()
的成本较高?)
你有什么看法?
你在这类问题上的习惯是什么?
编辑 09/07/2013
我最终花时间亲自测试了 @Qwerky 的 Share
类,发现结果相当...出乎意料。
该类缺少我最关心的内容:像 GenericObjectPool 或 StackObjectPool 这样的池。
因此,我重新设计了这个类来测试所有4种备选方案:
由于使用池时1M次循环需要太长时间,我将循环次数降低到100000。
我还在每个循环的末尾添加了Thread.yield()
以使负载更好地分配。
结果(累积运行时间):
- MessageDigest
- 新实例:420秒
- 单个实例:550秒
- StackObjectPool:800秒
- GenericObjectPool:1900秒
- KeyFactory
- 新实例:400秒
- 单个实例:350秒
- StackObjectPool:2900秒
- GenericObjectPool:3500秒
- SecureRandom
- StackObjectPool:1600秒
- 新实例:2300秒
- GenericObjectPool:2300秒
- 单个实例:2800秒
- Cipher
- StackObjectPool:2800秒
- GenericObjectPool:3500秒
- 单个实例:5100秒
- 新实例:8000秒
结论
对于MessageDigest和KeyFactory,池是性能杀手,甚至比具有同步瓶颈的单个实例更糟糕,而在SecureRandom和Cipher方面,它们确实非常有用。
MessageDigest
等。 - Qwerky