You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2010/11/17 18:59:49 UTC
svn commit: r1036145 - in /tomcat/trunk:
java/org/apache/catalina/session/ManagerBase.java
test/org/apache/catalina/session/Benchmarks.java
Author: markt
Date: Wed Nov 17 17:59:49 2010
New Revision: 1036145
URL: http://svn.apache.org/viewvc?rev=1036145&view=rev
Log:
Session manager performance
Switch to a queue of randomInputStreams
Significant performance improvement on multi-core non-Windows platforms
Modified:
tomcat/trunk/java/org/apache/catalina/session/ManagerBase.java
tomcat/trunk/test/org/apache/catalina/session/Benchmarks.java
Modified: tomcat/trunk/java/org/apache/catalina/session/ManagerBase.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/session/ManagerBase.java?rev=1036145&r1=1036144&r2=1036145&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/session/ManagerBase.java (original)
+++ tomcat/trunk/java/org/apache/catalina/session/ManagerBase.java Wed Nov 17 17:59:49 2010
@@ -76,7 +76,8 @@ public abstract class ManagerBase extend
// ----------------------------------------------------- Instance Variables
- protected volatile InputStream randomIS = null;
+ protected volatile Queue<InputStream> randomInputStreams =
+ new ConcurrentLinkedQueue<InputStream>();
protected String randomFile = "/dev/urandom";
protected String randomFileCurrent = null;
protected volatile boolean randomFileCurrentIsValid = true;
@@ -253,27 +254,28 @@ public abstract class ManagerBase extend
// ------------------------------------------------------------- Security classes
- private class PrivilegedCreateRandomIS implements PrivilegedAction<Void> {
+ private class PrivilegedCreateRandomInputStream
+ implements PrivilegedAction<InputStream> {
@Override
- public Void run(){
+ public InputStream run(){
try {
File f = new File(randomFileCurrent);
if (!f.exists()) {
randomFileCurrentIsValid = false;
- closeRandomFile();
+ closeRandomInputStreams();
return null;
}
InputStream is = new FileInputStream(f);
is.read();
if( log.isDebugEnabled() )
log.debug( "Opening " + randomFileCurrent );
- randomIS = is;
randomFileCurrentIsValid = true;
+ return is;
} catch (IOException ex){
log.warn("Error reading " + randomFileCurrent, ex);
randomFileCurrentIsValid = false;
- closeRandomFile();
+ closeRandomInputStreams();
}
return null;
}
@@ -570,28 +572,30 @@ public abstract class ManagerBase extend
randomFile = s;
}
- protected void createRandomIS() {
+ protected InputStream createRandomInputStream() {
if (Globals.IS_SECURITY_ENABLED){
- AccessController.doPrivileged(new PrivilegedCreateRandomIS());
+ return AccessController.doPrivileged(
+ new PrivilegedCreateRandomInputStream());
} else {
try{
File f = new File(randomFileCurrent);
if (!f.exists()) {
randomFileCurrentIsValid = false;
- closeRandomFile();
- return;
+ closeRandomInputStreams();
+ return null;
}
InputStream is = new FileInputStream(f);
is.read();
if( log.isDebugEnabled() )
log.debug( "Opening " + randomFileCurrent );
- randomIS = is;
randomFileCurrentIsValid = true;
+ return is;
} catch( IOException ex ) {
log.warn("Error reading " + randomFileCurrent, ex);
randomFileCurrentIsValid = false;
- closeRandomFile();
+ closeRandomInputStreams();
}
+ return null;
}
}
@@ -624,14 +628,16 @@ public abstract class ManagerBase extend
}
- protected synchronized void closeRandomFile() {
- if (randomIS != null) {
+ protected synchronized void closeRandomInputStreams() {
+ InputStream is = randomInputStreams.poll();
+
+ while (is != null) {
try {
- randomIS.close();
+ is.close();
} catch (Exception e) {
- log.warn("Failed to close randomIS.");
+ log.warn("Failed to close randomInputStream.");
}
- randomIS = null;
+ is = randomInputStreams.poll();
}
}
@@ -851,7 +857,10 @@ public abstract class ManagerBase extend
protected void startInternal() throws LifecycleException {
randomFileCurrent = randomFile;
- createRandomIS();
+ InputStream is = createRandomInputStream();
+ if (is != null) {
+ randomInputStreams.add(is);
+ }
// Force initialization of the random number generator
if (log.isDebugEnabled())
@@ -863,7 +872,7 @@ public abstract class ManagerBase extend
@Override
protected void stopInternal() throws LifecycleException {
- closeRandomFile();
+ closeRandomInputStreams();
}
@@ -1037,17 +1046,18 @@ public abstract class ManagerBase extend
protected void getRandomBytes(byte bytes[]) {
- if (randomIS != null) {
+ if (randomFileCurrentIsValid) {
+ InputStream is = null;
try {
- // If randomIS is set to null by a call to setRandomFile that
- // fails, the resulting NPE will trigger a fall-back to
- // getRandom()
- int len;
- synchronized (randomIS) {
- // FileInputStream is not thread safe on all platforms
- len = randomIS.read(bytes);
+ // If one of the InputStreams fails, is will be null and the
+ // resulting NPE will trigger a fall-back to getRandom()
+ is = randomInputStreams.poll();
+ if (is == null) {
+ is = createRandomInputStream();
}
+ int len = is.read(bytes);
if (len == bytes.length) {
+ randomInputStreams.add(is);
return;
}
if(log.isDebugEnabled())
@@ -1056,7 +1066,10 @@ public abstract class ManagerBase extend
// Ignore
}
randomFileCurrentIsValid = false;
- closeRandomFile();
+ if (is != null) {
+ randomInputStreams.add(is);
+ }
+ closeRandomInputStreams();
}
Random random = randoms.poll();
if (random == null) {
Modified: tomcat/trunk/test/org/apache/catalina/session/Benchmarks.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/session/Benchmarks.java?rev=1036145&r1=1036144&r2=1036145&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/session/Benchmarks.java (original)
+++ tomcat/trunk/test/org/apache/catalina/session/Benchmarks.java Wed Nov 17 17:59:49 2010
@@ -37,10 +37,10 @@ public class Benchmarks extends TestCase
* 16 threads - ~21,000ms
*
* Results on markt's 2-core OSX dev box
- * 1 thread - ~5,900ms
- * 2 threads - ~16,100ms
- * 4 threads - ~32,500ms
- * 16 threads - ~132,000ms
+ * 1 thread - ~5,600ms
+ * 2 threads - ~ 7,300ms
+ * 4 threads - ~14,400ms
+ * 16 threads - ~57,559ms
*/
public void testManagerBaseGenerateSessionId() throws Exception {
doTestManagerBaseGenerateSessionId(1, 1000000);
@@ -63,7 +63,7 @@ public class Benchmarks extends TestCase
StandardManager mgr = new StandardManager();
// Calling start requires a valid container so do the equivalent
mgr.randomFileCurrent = mgr.randomFile;
- mgr.createRandomIS();
+ mgr.createRandomInputStream();
mgr.generateSessionId();
@@ -125,10 +125,10 @@ public class Benchmarks extends TestCase
* 16 threads - ~43,800ms
*
* Results on markt's 2-core OSX dev box
- * 1 thread - ~8,800ms
- * 2 threads - ~23,200ms
- * 4 threads - ~51,900ms
- * 16 threads - ~215,400ms
+ * 1 thread - ~9,100ms
+ * 2 threads - ~10,800ms
+ * 4 threads - ~21,400ms
+ * 16 threads - ~87,600ms
*/
public void testManagerBaseCreateSession() {
doTestManagerBaseCreateSession(1, 1000000);
@@ -145,7 +145,7 @@ public class Benchmarks extends TestCase
mgr.setContainer(new StandardContext());
// Calling start requires a valid container so do the equivalent
mgr.randomFileCurrent = mgr.randomFile;
- mgr.createRandomIS();
+ mgr.createRandomInputStream();
mgr.generateSessionId();
Thread[] threads = new Thread[threadCount];
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org