300933 - AbstractConnector uses concurrent objects for stats

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@1217 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2010-01-27 09:20:05 +00:00
parent 1438977c5c
commit 4d65767692
5 changed files with 116 additions and 130 deletions

View File

@ -18,6 +18,7 @@ jetty-7.0.2-SNAPSHOT
+ JETTY-1151 JETTY-1098 allow UTF-8 with 0 carry bits
+ COMETD-46 reset ContentExchange response content on resend
+ 300178 HttpClients opens too many connections that are immediately closed
+ 300933 - AbstractConnector uses concurrent objects for stats
jetty-7.0.1.v20091125 25 November 2009
+ 274251 DefaultServlet supports exact match mode.

View File

@ -17,6 +17,8 @@ import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import javax.servlet.ServletRequest;
@ -75,23 +77,18 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
private transient Thread[] _acceptorThread;
final Object _statsLock = new Object();
transient long _statsStartedAt=-1;
private final AtomicLong _statsStartedAt = new AtomicLong(-1L);
// TODO use concurrents for these!
transient int _requests;
transient int _connections; // total number of connections made to server
private final AtomicInteger _requests = new AtomicInteger(); // total number of requests made to the server
private final AtomicInteger _connections = new AtomicInteger(); // total number of connections made to server
transient int _connectionsOpen; // number of connections currently open
transient int _connectionsOpenMin; // min number of connections open simultaneously
transient int _connectionsOpenMax; // max number of connections open simultaneously
private final AtomicInteger _connectionsOpen = new AtomicInteger(); // number of connections currently open
private final AtomicInteger _connectionsOpenMax = new AtomicInteger(); // max number of connections open simultaneously
transient long _connectionsDurationMin; // min duration of a connection
transient long _connectionsDurationMax; // max duration of a connection
transient long _connectionsDurationTotal; // total duration of all coneection
private final AtomicLong _connectionsDurationMax = new AtomicLong(); // max duration of a connection
private final AtomicLong _connectionsDurationTotal = new AtomicLong(); // total duration of all connection
transient int _connectionsRequestsMin; // min requests per connection
transient int _connectionsRequestsMax; // max requests per connection
private final AtomicInteger _connectionsRequestsMax = new AtomicInteger(); // max requests per connection
/* ------------------------------------------------------------------------------- */
@ -839,19 +836,13 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
/* ------------------------------------------------------------ */
/**
* @return Get the number of requests handled by this context
* @return Get the number of requests handled by this connector
* since last call of statsReset(). If setStatsOn(false) then this
* is undefined.
*/
public int getRequests() {return _requests;}
/* ------------------------------------------------------------ */
/**
* @return Returns the connectionsDurationMin.
*/
public long getConnectionsDurationMin()
public int getRequests()
{
return _connectionsDurationMin;
return _requests.get();
}
/* ------------------------------------------------------------ */
@ -860,110 +851,98 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
*/
public long getConnectionsDurationTotal()
{
return _connectionsDurationTotal;
return _connectionsDurationTotal.get();
}
/* ------------------------------------------------------------ */
/**
* @return Returns the connectionsOpenMin.
*/
public int getConnectionsOpenMin()
{
return _connectionsOpenMin;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the connectionsRequestsMin.
*/
public int getConnectionsRequestsMin()
{
return _connectionsRequestsMin;
}
/* ------------------------------------------------------------ */
/**
* @return Number of connections accepted by the server since
* statsReset() called. Undefined if setStatsOn(false).
*/
public int getConnections() {return _connections;}
public int getConnections() {return _connections.get();}
/* ------------------------------------------------------------ */
/**
* @return Number of connections currently open that were opened
* since statsReset() called. Undefined if setStatsOn(false).
*/
public int getConnectionsOpen() {return _connectionsOpen;}
public int getConnectionsOpen() {return _connectionsOpen.get();}
/* ------------------------------------------------------------ */
/**
* @return Maximum number of connections opened simultaneously
* since statsReset() called. Undefined if setStatsOn(false).
*/
public int getConnectionsOpenMax() {return _connectionsOpenMax;}
public int getConnectionsOpenMax() {return _connectionsOpenMax.get();}
/* ------------------------------------------------------------ */
/**
* @return Average duration in milliseconds of open connections
* since statsReset() called. Undefined if setStatsOn(false).
*/
public long getConnectionsDurationAve() {return _connections==0?0:(_connectionsDurationTotal/_connections);}
public long getConnectionsDurationAve()
{
int connections = getConnections();
return (connections==0) ? 0 : (getConnectionsDurationTotal()/connections);
}
/* ------------------------------------------------------------ */
/**
* @return Maximum duration in milliseconds of an open connection
* since statsReset() called. Undefined if setStatsOn(false).
*/
public long getConnectionsDurationMax() {return _connectionsDurationMax;}
public long getConnectionsDurationMax() {return _connectionsDurationMax.get();}
/* ------------------------------------------------------------ */
/**
* @return Average number of requests per connection
* since statsReset() called. Undefined if setStatsOn(false).
*/
public int getConnectionsRequestsAve() {return _connections==0?0:(_requests/_connections);}
public int getConnectionsRequestsAve()
{
int connections = getConnections();
return (connections==0) ? 0: (getRequests()/connections);
}
/* ------------------------------------------------------------ */
/**
* @return Maximum number of requests per connection
* since statsReset() called. Undefined if setStatsOn(false).
*/
public int getConnectionsRequestsMax() {return _connectionsRequestsMax;}
public int getConnectionsRequestsMax() {return _connectionsRequestsMax.get();}
/* ------------------------------------------------------------ */
/** Reset statistics.
*/
public void statsReset()
{
_statsStartedAt=_statsStartedAt==-1?-1:System.currentTimeMillis();
updateNotEqual(_statsStartedAt, -1, System.currentTimeMillis());
_connections=0;
_connections.set(0);
_connectionsOpenMin=_connectionsOpen;
_connectionsOpenMax=_connectionsOpen;
_connectionsOpen=0;
_connectionsOpenMax.set(_connectionsOpen.get());
_connectionsOpen.set(0);
_connectionsDurationMin=0;
_connectionsDurationMax=0;
_connectionsDurationTotal=0;
_connectionsDurationMax.set(0);
_connectionsDurationTotal.set(0);
_requests=0;
_requests.set(0);
_connectionsRequestsMin=0;
_connectionsRequestsMax=0;
_connectionsRequestsMax.set(0);
}
/* ------------------------------------------------------------ */
public void setStatsOn(boolean on)
{
if (on && _statsStartedAt!=-1)
if (on && _statsStartedAt.get()!=-1)
return;
Log.debug("Statistics on = "+on+" for "+this);
statsReset();
_statsStartedAt=on?System.currentTimeMillis():-1;
_statsStartedAt.set(on ? System.currentTimeMillis() : -1);
}
/* ------------------------------------------------------------ */
@ -972,7 +951,7 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
*/
public boolean getStatsOn()
{
return _statsStartedAt!=-1;
return _statsStartedAt.get()!=-1;
}
/* ------------------------------------------------------------ */
@ -981,62 +960,42 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
*/
public long getStatsOnMs()
{
return (_statsStartedAt!=-1)?(System.currentTimeMillis()-_statsStartedAt):0;
long start = _statsStartedAt.get();
return (start != -1) ? (System.currentTimeMillis()-start) : 0;
}
/* ------------------------------------------------------------ */
protected void connectionOpened(Connection connection)
{
if (_statsStartedAt==-1)
if (_statsStartedAt.get()==-1)
return;
synchronized(_statsLock)
{
_connectionsOpen++;
if (_connectionsOpen > _connectionsOpenMax)
_connectionsOpenMax=_connectionsOpen;
}
updateMax(_connectionsOpenMax, _connectionsOpen.incrementAndGet());
}
/* ------------------------------------------------------------ */
protected void connectionUpgraded(Connection oldConnection,Connection newConnection)
protected void connectionUpgraded(Connection oldConnection, Connection newConnection)
{
int requests=(oldConnection instanceof HttpConnection)?((HttpConnection)oldConnection).getRequests():0;
synchronized(_statsLock)
{
_requests+=requests;
}
_requests.addAndGet((oldConnection instanceof HttpConnection)?((HttpConnection)oldConnection).getRequests():0);
}
/* ------------------------------------------------------------ */
protected void connectionClosed(Connection connection)
{
if (_statsStartedAt>=0)
{
long duration=System.currentTimeMillis()-connection.getTimeStamp();
int requests=(connection instanceof HttpConnection)?((HttpConnection)connection).getRequests():0;
if (_statsStartedAt.get()==-1)
return;
long duration = System.currentTimeMillis() - connection.getTimeStamp();
int requests = (connection instanceof HttpConnection) ? ((HttpConnection)connection).getRequests() : 0;
synchronized(_statsLock)
{
_requests+=requests;
_connections++;
_connectionsOpen--;
_connectionsDurationTotal+=duration;
if (_connectionsOpen<0)
_connectionsOpen=0;
if (_connectionsOpen<_connectionsOpenMin)
_connectionsOpenMin=_connectionsOpen;
if (_connectionsDurationMin==0 || duration<_connectionsDurationMin)
_connectionsDurationMin=duration;
if (duration>_connectionsDurationMax)
_connectionsDurationMax=duration;
if (_connectionsRequestsMin==0 || requests<_connectionsRequestsMin)
_connectionsRequestsMin=requests;
if (requests>_connectionsRequestsMax)
_connectionsRequestsMax=requests;
}
}
_requests.addAndGet(requests);
_connections.incrementAndGet();
_connectionsOpen.decrementAndGet();
_connectionsDurationTotal.addAndGet(duration);
updateMax(_connectionsDurationMax, duration);
updateMax(_connectionsRequestsMax, requests);
}
@ -1086,4 +1045,40 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
return _threadPool.isLowOnThreads();
return _server.getThreadPool().isLowOnThreads();
}
/* ------------------------------------------------------------ */
private void updateNotEqual(AtomicLong valueHolder, long compare, long value)
{
long oldValue = valueHolder.get();
while (compare != oldValue)
{
if (valueHolder.compareAndSet(oldValue, value))
break;
oldValue = valueHolder.get();
}
}
/* ------------------------------------------------------------ */
private void updateMax(AtomicInteger valueHolder, int value)
{
int oldValue = valueHolder.get();
while (value > oldValue)
{
if (valueHolder.compareAndSet(oldValue, value))
break;
oldValue = valueHolder.get();
}
}
/* ------------------------------------------------------------ */
private void updateMax(AtomicLong valueHolder, long value)
{
long oldValue = valueHolder.get();
while (value > oldValue)
{
if (valueHolder.compareAndSet(oldValue, value))
break;
oldValue = valueHolder.get();
}
}
}

View File

@ -248,30 +248,11 @@ public interface Connector extends LifeCycle
*/
public int getRequests();
/* ------------------------------------------------------------ */
/**
* @return Returns the connectionsDurationMin.
*/
public long getConnectionsDurationMin();
/* ------------------------------------------------------------ */
/**
* @return Returns the connectionsDurationTotal.
*/
public long getConnectionsDurationTotal();
/* ------------------------------------------------------------ */
/**
* @return Returns the connectionsOpenMin.
*/
public int getConnectionsOpenMin();
/* ------------------------------------------------------------ */
/**
* @return Returns the connectionsRequestsMin.
*/
public int getConnectionsRequestsMin();
/* ------------------------------------------------------------ */
/**

View File

@ -46,6 +46,7 @@ public class StatisticsHandlerTest extends TestCase
_connector = new LocalConnector();
_server.addConnector(_connector);
_connector.setStatsOn(true);
_latchHandler = new LatchHandler();
_statsHandler = new StatisticsHandler();
@ -91,6 +92,8 @@ public class StatisticsHandlerTest extends TestCase
_connector.executeRequest(request);
barrier[0].await();
assertEquals(1, _connector.getConnectionsOpen());
assertEquals(0, _statsHandler.getRequests());
assertEquals(1, _statsHandler.getRequestsActive());
@ -126,6 +129,8 @@ public class StatisticsHandlerTest extends TestCase
barrier[0].await();
assertEquals(2, _connector.getConnectionsOpen());
assertEquals(1, _statsHandler.getRequests());
assertEquals(1, _statsHandler.getRequestsActive());
assertEquals(1, _statsHandler.getRequestsActiveMax());
@ -161,6 +166,8 @@ public class StatisticsHandlerTest extends TestCase
barrier[0].await();
assertEquals(4, _connector.getConnectionsOpen());
assertEquals(2, _statsHandler.getRequests());
assertEquals(2, _statsHandler.getRequestsActive());
assertEquals(2, _statsHandler.getRequestsActiveMax());
@ -242,6 +249,8 @@ public class StatisticsHandlerTest extends TestCase
barrier[0].await();
assertEquals(1, _connector.getConnectionsOpen());
assertEquals(0, _statsHandler.getRequests());
assertEquals(1, _statsHandler.getRequestsActive());
@ -280,6 +289,8 @@ public class StatisticsHandlerTest extends TestCase
barrier[0].await();
assertEquals(1, _connector.getConnectionsOpen());
assertEquals(0, _statsHandler.getRequests());
assertEquals(1, _statsHandler.getRequestsActive());
assertEquals(1, _statsHandler.getDispatched());
@ -364,6 +375,8 @@ public class StatisticsHandlerTest extends TestCase
barrier[0].await();
assertEquals(1, _connector.getConnectionsOpen());
assertEquals(0, _statsHandler.getRequests());
assertEquals(1, _statsHandler.getRequestsActive());
@ -481,6 +494,8 @@ public class StatisticsHandlerTest extends TestCase
barrier[0].await();
assertEquals(1, _connector.getConnectionsOpen());
assertEquals(0, _statsHandler.getRequests());
assertEquals(1, _statsHandler.getRequestsActive());

View File

@ -151,15 +151,12 @@ public class StatisticsServlet extends HttpServlet
sb.append(" <statsOnMs>").append(connector.getStatsOnMs()).append("</statsOnMs>\n");
sb.append(" <connections>").append(connector.getConnections()).append("</connections>\n");
sb.append(" <connectionsOpen>").append(connector.getConnectionsOpen()).append("</connectionsOpen>\n");
sb.append(" <connectionsOpenMin>").append(connector.getConnectionsOpenMin()).append("</connectionsOpenMin>\n");
sb.append(" <connectionsOpenMax>").append(connector.getConnectionsOpenMax()).append("</connectionsOpenMax>\n");
sb.append(" <connectionsDurationTotal>").append(connector.getConnectionsDurationTotal()).append("</connectionsDurationTotal>\n");
sb.append(" <connectionsDurationAve>").append(connector.getConnectionsDurationAve()).append("</connectionsDurationAve>\n");
sb.append(" <connectionsDurationMin>").append(connector.getConnectionsDurationMin()).append("</connectionsDurationMin>\n");
sb.append(" <connectionsDurationMax>").append(connector.getConnectionsDurationMax()).append("</connectionsDurationMax>\n");
sb.append(" <requests>").append(connector.getRequests()).append("</requests>\n");
sb.append(" <connectionsRequestsAve>").append(connector.getConnectionsRequestsAve()).append("</connectionsRequestsAve>\n");
sb.append(" <connectionsRequestsMin>").append(connector.getConnectionsRequestsMin()).append("</connectionsRequestsMin>\n");
sb.append(" <connectionsRequestsMax>").append(connector.getConnectionsRequestsMax()).append("</connectionsRequestsMax>\n");
}
sb.append(" </connector>\n");
@ -193,15 +190,12 @@ public class StatisticsServlet extends HttpServlet
sb.append("Statistics gathering started ").append(connector.getStatsOnMs()).append("ms ago").append("<br />\n");
sb.append("Total connections: ").append(connector.getConnections()).append("<br />\n");
sb.append("Current connections open: ").append(connector.getConnectionsOpen());
sb.append("Min concurrent connections open: ").append(connector.getConnectionsOpenMin()).append("<br />\n");
sb.append("Max concurrent connections open: ").append(connector.getConnectionsOpenMax()).append("<br />\n");
sb.append("Total connections duration: ").append(connector.getConnectionsDurationTotal()).append("<br />\n");
sb.append("Average connection duration: ").append(connector.getConnectionsDurationAve()).append("<br />\n");
sb.append("Min connection duration: ").append(connector.getConnectionsDurationMin()).append("<br />\n");
sb.append("Max connection duration: ").append(connector.getConnectionsDurationMax()).append("<br />\n");
sb.append("Total requests: ").append(connector.getRequests()).append("<br />\n");
sb.append("Average requests per connection: ").append(connector.getConnectionsRequestsAve()).append("<br />\n");
sb.append("Min requests per connection: ").append(connector.getConnectionsRequestsMin()).append("<br />\n");
sb.append("Max requests per connection: ").append(connector.getConnectionsRequestsMax()).append("<br />\n");
}
else