From e893ec113983b7a6847d689ec33bccdb58c57a94 Mon Sep 17 00:00:00 2001 From: fhanik Date: Fri, 24 Jul 2009 15:24:52 +0000 Subject: [PATCH] Add in Linux special case for performance optimization around locking. Set default queue to be the fair one Remove unused code git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@797528 13f79535-47bb-0310-9956-ffa450edef68 --- modules/jdbc-pool/doc/jdbc-pool.xml | 12 +++++++++--- .../org/apache/tomcat/jdbc/pool/ConnectionPool.java | 19 ++++--------------- .../org/apache/tomcat/jdbc/pool/DataSourceProxy.java | 11 ----------- .../apache/tomcat/jdbc/pool/FairBlockingQueue.java | 18 +++++++++++++++++- .../apache/tomcat/jdbc/pool/PoolConfiguration.java | 2 +- .../org/apache/tomcat/jdbc/pool/PoolProperties.java | 2 +- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/modules/jdbc-pool/doc/jdbc-pool.xml b/modules/jdbc-pool/doc/jdbc-pool.xml index 800d89604..45821c68f 100644 --- a/modules/jdbc-pool/doc/jdbc-pool.xml +++ b/modules/jdbc-pool/doc/jdbc-pool.xml @@ -353,10 +353,16 @@

(boolean) Set to true if you wish that calls to getConnection should be treated fairly in a true FIFO fashion. This uses the org.apache.tomcat.jdbc.pool.FairBlockingQueue - implementation for the list of the idle connections. The default value is false. + implementation for the list of the idle connections. The default value is true. This flag is required when you want to use asynchronous connection retrieval.
- During performance tests, the fairQueue does very well on a multi core Solaris system, - but performs terribly on a Linux Fedora 11 system. On Linux we recommend setting this to false. + Setting this flag ensures that threads receive connections in the order they arrive.
+ During performance tests, there is a very large difference in how locks + and lock waiting is implemented. When fairQueue=true> + there is a decision making process based on what operating system the system is running. + If the system is running on Linux (property os.name=Linux. + To disable this Linux specific behavior and still use the fair queue, simply add the property + org.apache.tomcat.jdbc.pool.FairBlockingQueue.ignoreOS=true to your system properties + before the connection pool classes are loaded.

diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java index 9250dac90..948034eaa 100644 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java +++ b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java @@ -148,6 +148,9 @@ public class ConnectionPool { if (idle instanceof FairBlockingQueue) { Future pcf = ((FairBlockingQueue)idle).pollAsync(); return new ConnectionFuture(pcf); + } else if (idle instanceof MultiLockFairBlockingQueue) { + Future pcf = ((MultiLockFairBlockingQueue)idle).pollAsync(); + return new ConnectionFuture(pcf); } else { throw new SQLException("Connection pool is misconfigured, doesn't support async retrieval. Set the 'fair' property to 'true'"); } @@ -306,21 +309,6 @@ public class ConnectionPool { } /** - * If the connection pool gets garbage collected, lets make sure we clean up - * and close all the connections. - * {@inheritDoc} - */ - @Override - protected void finalize() throws Throwable { -// Runnable closer = new Runnable() { -// public void run() { -// close(true); -// } -// }; -// this.cancellator.execute(closer); - } - - /** * Closes the pool and all disconnects all idle connections * Active connections will be closed upon the {@link java.sql.Connection#close close} method is called * on the underlying connection instead of being returned to the pool @@ -381,6 +369,7 @@ public class ConnectionPool { //make space for 10 extra in case we flow over a bit if (properties.isFairQueue()) { idle = new FairBlockingQueue(); + //idle = new MultiLockFairBlockingQueue(); } else { idle = new ArrayBlockingQueue(properties.getMaxActive(),properties.isFairQueue()); } diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java index 12d94d522..3c1934cb4 100644 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java +++ b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java @@ -155,17 +155,6 @@ public class DataSourceProxy implements PoolConfiguration { } } - protected void finalize() throws Throwable { -// //terminate the pool? -// ThreadPoolExecutor closer = new ThreadPoolExecutor(0,1,1000,TimeUnit.MILLISECONDS,new LinkedBlockingQueue()); -// final Runnable r = new Runnable() { -// public void run(){ -// close(true); -// } -// }; -// closer.execute(r); - } - public int getPoolSize() throws SQLException{ final ConnectionPool p = pool; if (p == null) return 0; diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/FairBlockingQueue.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/FairBlockingQueue.java index 74a3ca2f2..992e80a05 100644 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/FairBlockingQueue.java +++ b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/FairBlockingQueue.java @@ -43,6 +43,20 @@ import java.util.concurrent.locks.ReentrantLock; public class FairBlockingQueue implements BlockingQueue { /** + * This little sucker is used to reorder the way to do + * {@link java.util.concurrent.locks.Lock#lock()}, + * {@link java.util.concurrent.locks.Lock#unlock()} + * and + * {@link java.util.concurrent.CountDownLatch#countDown()} + * during the {@link #poll(long, TimeUnit)} operation. + * On Linux, it performs much better if we count down while we hold the global + * lock, on Solaris its the other way around. + * Until we have tested other platforms we only check for Linux. + */ + final static boolean isLinux = "Linux".equals(System.getProperty("os.name")) && + (!Boolean.getBoolean(FairBlockingQueue.class.getName()+".ignoreOS")); + + /** * Phase one entry lock in order to give out * per-thread-locks for the waiting phase we have * a phase one lock during the contention period. @@ -86,6 +100,7 @@ public class FairBlockingQueue implements BlockingQueue { c = waiters.poll(); //give the object to the thread instead of adding it to the pool c.setItem(e); + if (isLinux && c!=null) c.countDown(); } else { //we always add first, so that the most recently used object will be given out items.addFirst(e); @@ -94,7 +109,7 @@ public class FairBlockingQueue implements BlockingQueue { lock.unlock(); } //if we exchanged an object with another thread, wake it up. - if (c!=null) c.countDown(); + if (!isLinux && c!=null) c.countDown(); //we have an unbounded queue, so always return true return true; } @@ -261,6 +276,7 @@ public class FairBlockingQueue implements BlockingQueue { * {@inheritDoc} * @throws UnsupportedOperation - this operation is not supported */ + public int drainTo(Collection c) { return drainTo(c,Integer.MAX_VALUE); } diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java index 967356256..667ae627b 100644 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java +++ b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java @@ -65,7 +65,7 @@ public interface PoolConfiguration { * Set to true if you wish that calls to getConnection * should be treated fairly in a true FIFO fashion. * This uses the {@link FairBlockingQueue} implementation for the list of the idle connections. - * The default value is false. + * The default value is true. * This flag is required when you want to use asynchronous connection retrieval. * @param fairQueue */ diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java index a43461e8a..73ef6efbe 100644 --- a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java +++ b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java @@ -68,7 +68,7 @@ public class PoolProperties implements PoolConfiguration { protected String initSQL; protected boolean testOnConnect =false; protected String jdbcInterceptors=null; - protected boolean fairQueue = false; + protected boolean fairQueue = true; protected boolean useEquals = false; protected int abandonWhenPercentageFull = 0; protected long maxAge = 0; -- 2.11.0