Minimizing SecureRandom performance problems in mu

2019-05-04 08:47发布

问题:

(This is with Java 8 and Tomcat 8 on SLES, FWIW.)

How worried do I need to be about performance problems with SecureRandom (specifically the SHA1PRNG algorithm of the SUN provider) after the initial seeding when I am using a single SecureRandom instance in multiple threads? SecureRandom is thread-safe so that implies some level of potential contention?

I don't see anything in Java 8 Javadocs that discusses this for SecureRandom though I see that the Javadocs for Random do specifically warn about contention and performance degradation when using a single Random instance across threads.

We are considering using a single SecureRandom instance because from what we see it is way too expensive to get a new SecureRandom instance within our encrypt() method (which uses SecureRandom for IV generation) because of the seeding overhead kills you if you use a new SecureRandom very few times before you are done with it.

We are alternatively considering having a static ThreadLocal<SecureRandom> member of the class containing the encrypt() method so that a single SecureRandom is used per thread. We would intentionally not call ThreadLocal.remove() because if we went this route we would actually like the instance to "live" in the tomcat threads as long as possible (to minimize the number of times new SecureRandom instances are created).

From reading here about ThreadLocal memory leaks I have some concerns about that approach. However, we literally never redeploy the webapp. It is used in an embedded system and when the webapp is upgraded (which is part of an overall system upgrade and only happens a few times a year) Tomcat is completely shut down, the new war file dropped down, and Tomcat restarted. That would seem to be to make the webapp-related ThreadLocal leaks moot.

So, is there any good data out there on how "contentious" SecureRandom is, and is there consensus on how to most properly use SecureRandom in a heavily-multithreaded environment?

回答1:

Looking at the source code of SecureRandom, it uses a synchronized method, so any discussion out there about synchronized in a heavily-multithreaded environment would be applicable.

Given this note (as you mentioned) in the Random javadoc, I'd say that your plan to use ThreadLocal<SecureRandom> is appropriate:

Instances of java.util.Random are threadsafe. However, the concurrent use of the same java.util.Random instance across threads may encounter contention and consequent poor performance. Consider instead using ThreadLocalRandom in multithreaded designs.

As you concluded yourself, you won't have memory leak issues with your implementation. This is especially true because the objects stored in the ThreadLocal are from the system ClassLoader, not your webapp's ClassLoader.