Merge remote-tracking branch 'origin/jetty-9.3.x'
This commit is contained in:
commit
92904d2b7d
|
@ -29,6 +29,7 @@ import org.eclipse.jetty.deploy.providers.WebAppProvider;
|
||||||
import org.eclipse.jetty.http.HttpVersion;
|
import org.eclipse.jetty.http.HttpVersion;
|
||||||
import org.eclipse.jetty.jmx.MBeanContainer;
|
import org.eclipse.jetty.jmx.MBeanContainer;
|
||||||
import org.eclipse.jetty.security.HashLoginService;
|
import org.eclipse.jetty.security.HashLoginService;
|
||||||
|
import org.eclipse.jetty.server.ConnectorStatistics;
|
||||||
import org.eclipse.jetty.server.DebugListener;
|
import org.eclipse.jetty.server.DebugListener;
|
||||||
import org.eclipse.jetty.server.Handler;
|
import org.eclipse.jetty.server.Handler;
|
||||||
import org.eclipse.jetty.server.HttpConfiguration;
|
import org.eclipse.jetty.server.HttpConfiguration;
|
||||||
|
@ -185,6 +186,7 @@ public class LikeJettyXml
|
||||||
StatisticsHandler stats = new StatisticsHandler();
|
StatisticsHandler stats = new StatisticsHandler();
|
||||||
stats.setHandler(server.getHandler());
|
stats.setHandler(server.getHandler());
|
||||||
server.setHandler(stats);
|
server.setHandler(stats);
|
||||||
|
ConnectorStatistics.addToAllConnectors(server);
|
||||||
|
|
||||||
|
|
||||||
// === jetty-requestlog.xml ===
|
// === jetty-requestlog.xml ===
|
||||||
|
|
|
@ -24,8 +24,8 @@ import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
import java.util.concurrent.atomic.LongAdder;
|
||||||
|
|
||||||
import org.eclipse.jetty.io.Connection;
|
import org.eclipse.jetty.io.Connection;
|
||||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||||
|
@ -54,8 +54,8 @@ public class ConnectorStatistics extends AbstractLifeCycle implements Dumpable,
|
||||||
private final SampleStatistic _messagesOut = new SampleStatistic();
|
private final SampleStatistic _messagesOut = new SampleStatistic();
|
||||||
private final SampleStatistic _connectionDurationStats = new SampleStatistic();
|
private final SampleStatistic _connectionDurationStats = new SampleStatistic();
|
||||||
private final ConcurrentMap<Connection, Sample> _samples = new ConcurrentHashMap<>();
|
private final ConcurrentMap<Connection, Sample> _samples = new ConcurrentHashMap<>();
|
||||||
private final AtomicInteger _closedIn = new AtomicInteger();
|
private final LongAdder _closedIn = new LongAdder();
|
||||||
private final AtomicInteger _closedOut = new AtomicInteger();
|
private final LongAdder _closedOut = new LongAdder();
|
||||||
private AtomicLong _nanoStamp=new AtomicLong();
|
private AtomicLong _nanoStamp=new AtomicLong();
|
||||||
private volatile int _messagesInPerSecond;
|
private volatile int _messagesInPerSecond;
|
||||||
private volatile int _messagesOutPerSecond;
|
private volatile int _messagesOutPerSecond;
|
||||||
|
@ -85,8 +85,8 @@ public class ConnectorStatistics extends AbstractLifeCycle implements Dumpable,
|
||||||
Sample sample=_samples.remove(connection);
|
Sample sample=_samples.remove(connection);
|
||||||
if (sample!=null)
|
if (sample!=null)
|
||||||
{
|
{
|
||||||
_closedIn.addAndGet(msgsIn-sample._messagesIn);
|
_closedIn.add(msgsIn-sample._messagesIn);
|
||||||
_closedOut.addAndGet(msgsOut-sample._messagesOut);
|
_closedOut.add(msgsOut-sample._messagesOut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,8 +267,8 @@ public class ConnectorStatistics extends AbstractLifeCycle implements Dumpable,
|
||||||
{
|
{
|
||||||
if (_nanoStamp.compareAndSet(then,now))
|
if (_nanoStamp.compareAndSet(then,now))
|
||||||
{
|
{
|
||||||
long msgsIn=_closedIn.getAndSet(0);
|
long msgsIn=_closedIn.sumThenReset();
|
||||||
long msgsOut=_closedOut.getAndSet(0);
|
long msgsOut=_closedOut.sumThenReset();
|
||||||
|
|
||||||
for (Map.Entry<Connection, Sample> entry : _samples.entrySet())
|
for (Map.Entry<Connection, Sample> entry : _samples.entrySet())
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,9 +22,9 @@ import java.io.IOException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.concurrent.atomic.LongAdder;
|
||||||
|
|
||||||
import javax.servlet.AsyncEvent;
|
import javax.servlet.AsyncEvent;
|
||||||
import javax.servlet.AsyncListener;
|
import javax.servlet.AsyncListener;
|
||||||
|
@ -60,15 +60,15 @@ public class StatisticsHandler extends HandlerWrapper implements Graceful
|
||||||
private final SampleStatistic _dispatchedTimeStats = new SampleStatistic();
|
private final SampleStatistic _dispatchedTimeStats = new SampleStatistic();
|
||||||
private final CounterStatistic _asyncWaitStats = new CounterStatistic();
|
private final CounterStatistic _asyncWaitStats = new CounterStatistic();
|
||||||
|
|
||||||
private final AtomicInteger _asyncDispatches = new AtomicInteger();
|
private final LongAdder _asyncDispatches = new LongAdder();
|
||||||
private final AtomicInteger _expires = new AtomicInteger();
|
private final LongAdder _expires = new LongAdder();
|
||||||
|
|
||||||
private final AtomicInteger _responses1xx = new AtomicInteger();
|
private final LongAdder _responses1xx = new LongAdder();
|
||||||
private final AtomicInteger _responses2xx = new AtomicInteger();
|
private final LongAdder _responses2xx = new LongAdder();
|
||||||
private final AtomicInteger _responses3xx = new AtomicInteger();
|
private final LongAdder _responses3xx = new LongAdder();
|
||||||
private final AtomicInteger _responses4xx = new AtomicInteger();
|
private final LongAdder _responses4xx = new LongAdder();
|
||||||
private final AtomicInteger _responses5xx = new AtomicInteger();
|
private final LongAdder _responses5xx = new LongAdder();
|
||||||
private final AtomicLong _responsesTotalBytes = new AtomicLong();
|
private final LongAdder _responsesTotalBytes = new LongAdder();
|
||||||
|
|
||||||
private final AtomicReference<FutureCallback> _shutdown=new AtomicReference<>();
|
private final AtomicReference<FutureCallback> _shutdown=new AtomicReference<>();
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ public class StatisticsHandler extends HandlerWrapper implements Graceful
|
||||||
@Override
|
@Override
|
||||||
public void onTimeout(AsyncEvent event) throws IOException
|
public void onTimeout(AsyncEvent event) throws IOException
|
||||||
{
|
{
|
||||||
_expires.incrementAndGet();
|
_expires.increment();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -132,14 +132,14 @@ public class StatisticsHandler extends HandlerWrapper implements Graceful
|
||||||
_dispatchedTimeStats.reset();
|
_dispatchedTimeStats.reset();
|
||||||
_asyncWaitStats.reset();
|
_asyncWaitStats.reset();
|
||||||
|
|
||||||
_asyncDispatches.set(0);
|
_asyncDispatches.reset();
|
||||||
_expires.set(0);
|
_expires.reset();
|
||||||
_responses1xx.set(0);
|
_responses1xx.reset();
|
||||||
_responses2xx.set(0);
|
_responses2xx.reset();
|
||||||
_responses3xx.set(0);
|
_responses3xx.reset();
|
||||||
_responses4xx.set(0);
|
_responses4xx.reset();
|
||||||
_responses5xx.set(0);
|
_responses5xx.reset();
|
||||||
_responsesTotalBytes.set(0L);
|
_responsesTotalBytes.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -159,7 +159,7 @@ public class StatisticsHandler extends HandlerWrapper implements Graceful
|
||||||
{
|
{
|
||||||
// resumed request
|
// resumed request
|
||||||
start = System.currentTimeMillis();
|
start = System.currentTimeMillis();
|
||||||
_asyncDispatches.incrementAndGet();
|
_asyncDispatches.increment();
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -221,19 +221,19 @@ public class StatisticsHandler extends HandlerWrapper implements Graceful
|
||||||
switch (response.getStatus() / 100)
|
switch (response.getStatus() / 100)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
_responses1xx.incrementAndGet();
|
_responses1xx.increment();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
_responses2xx.incrementAndGet();
|
_responses2xx.increment();
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
_responses3xx.incrementAndGet();
|
_responses3xx.increment();
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
_responses4xx.incrementAndGet();
|
_responses4xx.increment();
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
_responses5xx.incrementAndGet();
|
_responses5xx.increment();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -241,8 +241,8 @@ public class StatisticsHandler extends HandlerWrapper implements Graceful
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// will fall through to not found handler
|
// will fall through to not found handler
|
||||||
_responses4xx.incrementAndGet();
|
_responses4xx.increment();
|
||||||
_responsesTotalBytes.addAndGet(response.getContentCount());
|
_responsesTotalBytes.add(response.getContentCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -454,7 +454,7 @@ public class StatisticsHandler extends HandlerWrapper implements Graceful
|
||||||
@ManagedAttribute("number of requested that have been asynchronously dispatched")
|
@ManagedAttribute("number of requested that have been asynchronously dispatched")
|
||||||
public int getAsyncDispatches()
|
public int getAsyncDispatches()
|
||||||
{
|
{
|
||||||
return _asyncDispatches.get();
|
return _asyncDispatches.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -464,7 +464,7 @@ public class StatisticsHandler extends HandlerWrapper implements Graceful
|
||||||
@ManagedAttribute("number of async requests requests that have expired")
|
@ManagedAttribute("number of async requests requests that have expired")
|
||||||
public int getExpires()
|
public int getExpires()
|
||||||
{
|
{
|
||||||
return _expires.get();
|
return _expires.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -474,7 +474,7 @@ public class StatisticsHandler extends HandlerWrapper implements Graceful
|
||||||
@ManagedAttribute("number of requests with 1xx response status")
|
@ManagedAttribute("number of requests with 1xx response status")
|
||||||
public int getResponses1xx()
|
public int getResponses1xx()
|
||||||
{
|
{
|
||||||
return _responses1xx.get();
|
return _responses1xx.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -484,7 +484,7 @@ public class StatisticsHandler extends HandlerWrapper implements Graceful
|
||||||
@ManagedAttribute("number of requests with 2xx response status")
|
@ManagedAttribute("number of requests with 2xx response status")
|
||||||
public int getResponses2xx()
|
public int getResponses2xx()
|
||||||
{
|
{
|
||||||
return _responses2xx.get();
|
return _responses2xx.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -494,7 +494,7 @@ public class StatisticsHandler extends HandlerWrapper implements Graceful
|
||||||
@ManagedAttribute("number of requests with 3xx response status")
|
@ManagedAttribute("number of requests with 3xx response status")
|
||||||
public int getResponses3xx()
|
public int getResponses3xx()
|
||||||
{
|
{
|
||||||
return _responses3xx.get();
|
return _responses3xx.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -504,7 +504,7 @@ public class StatisticsHandler extends HandlerWrapper implements Graceful
|
||||||
@ManagedAttribute("number of requests with 4xx response status")
|
@ManagedAttribute("number of requests with 4xx response status")
|
||||||
public int getResponses4xx()
|
public int getResponses4xx()
|
||||||
{
|
{
|
||||||
return _responses4xx.get();
|
return _responses4xx.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -514,7 +514,7 @@ public class StatisticsHandler extends HandlerWrapper implements Graceful
|
||||||
@ManagedAttribute("number of requests with 5xx response status")
|
@ManagedAttribute("number of requests with 5xx response status")
|
||||||
public int getResponses5xx()
|
public int getResponses5xx()
|
||||||
{
|
{
|
||||||
return _responses5xx.get();
|
return _responses5xx.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -532,7 +532,7 @@ public class StatisticsHandler extends HandlerWrapper implements Graceful
|
||||||
@ManagedAttribute("total number of bytes across all responses")
|
@ManagedAttribute("total number of bytes across all responses")
|
||||||
public long getResponsesBytesTotal()
|
public long getResponsesBytesTotal()
|
||||||
{
|
{
|
||||||
return _responsesTotalBytes.get();
|
return _responsesTotalBytes.longValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toStatsHTML()
|
public String toStatsHTML()
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.server.jmx;
|
||||||
|
|
||||||
import org.eclipse.jetty.jmx.ObjectMBean;
|
import org.eclipse.jetty.jmx.ObjectMBean;
|
||||||
import org.eclipse.jetty.server.AbstractConnector;
|
import org.eclipse.jetty.server.AbstractConnector;
|
||||||
|
import org.eclipse.jetty.server.ConnectionFactory;
|
||||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||||
|
|
||||||
@ManagedObject("MBean Wrapper for Connectors")
|
@ManagedObject("MBean Wrapper for Connectors")
|
||||||
|
@ -31,10 +32,23 @@ public class AbstractConnectorMBean extends ObjectMBean
|
||||||
super(managedObject);
|
super(managedObject);
|
||||||
_connector=(AbstractConnector)managedObject;
|
_connector=(AbstractConnector)managedObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getObjectContextBasis()
|
public String getObjectContextBasis()
|
||||||
{
|
{
|
||||||
return String.format("%s@%x",_connector.getDefaultProtocol(),_connector.hashCode());
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
for (ConnectionFactory f:_connector.getConnectionFactories())
|
||||||
|
{
|
||||||
|
String protocol=f.getProtocol();
|
||||||
|
if (protocol!=null)
|
||||||
|
{
|
||||||
|
if (buffer.length()>0)
|
||||||
|
buffer.append("|");
|
||||||
|
buffer.append(protocol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.format("%s@%x",buffer.toString(),_connector.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,8 @@
|
||||||
package org.eclipse.jetty.util.statistic;
|
package org.eclipse.jetty.util.statistic;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
import java.util.concurrent.atomic.LongAccumulator;
|
||||||
import org.eclipse.jetty.util.Atomics;
|
import java.util.concurrent.atomic.LongAdder;
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
/** Statistics on a counter value.
|
/** Statistics on a counter value.
|
||||||
|
@ -33,30 +32,30 @@ import org.eclipse.jetty.util.Atomics;
|
||||||
*/
|
*/
|
||||||
public class CounterStatistic
|
public class CounterStatistic
|
||||||
{
|
{
|
||||||
protected final AtomicLong _max = new AtomicLong();
|
protected final LongAccumulator _max = new LongAccumulator(Math::max,0L);
|
||||||
protected final AtomicLong _curr = new AtomicLong();
|
protected final AtomicLong _current = new AtomicLong();
|
||||||
protected final AtomicLong _total = new AtomicLong();
|
protected final LongAdder _total = new LongAdder();
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
public void reset()
|
public void reset()
|
||||||
{
|
{
|
||||||
_total.set(0);
|
_total.reset();
|
||||||
_max.set(0);
|
_max.reset();
|
||||||
long current=_curr.get();
|
long current=_current.get();
|
||||||
_total.addAndGet(current);
|
_total.add(current);
|
||||||
Atomics.updateMax(_max,current);
|
_max.accumulate(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
public void reset(final long value)
|
public void reset(final long value)
|
||||||
{
|
{
|
||||||
_total.set(0);
|
_current.set(value);
|
||||||
_max.set(0);
|
_total.reset();
|
||||||
_curr.set(value);
|
_max.reset();
|
||||||
if (value>0)
|
if (value>0)
|
||||||
{
|
{
|
||||||
_total.addAndGet(value);
|
_total.add(value);
|
||||||
Atomics.updateMax(_max,value);
|
_max.accumulate(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,11 +66,11 @@ public class CounterStatistic
|
||||||
*/
|
*/
|
||||||
public long add(final long delta)
|
public long add(final long delta)
|
||||||
{
|
{
|
||||||
long value=_curr.addAndGet(delta);
|
long value=_current.addAndGet(delta);
|
||||||
if (delta > 0)
|
if (delta > 0)
|
||||||
{
|
{
|
||||||
_total.addAndGet(delta);
|
_total.add(delta);
|
||||||
Atomics.updateMax(_max,value);
|
_max.accumulate(value);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +82,10 @@ public class CounterStatistic
|
||||||
*/
|
*/
|
||||||
public long increment()
|
public long increment()
|
||||||
{
|
{
|
||||||
return add(1);
|
long value=_current.incrementAndGet();
|
||||||
|
_total.increment();
|
||||||
|
_max.accumulate(value);
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
|
@ -93,7 +95,7 @@ public class CounterStatistic
|
||||||
*/
|
*/
|
||||||
public long decrement()
|
public long decrement()
|
||||||
{
|
{
|
||||||
return add(-1);
|
return _current.decrementAndGet();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
|
@ -111,7 +113,7 @@ public class CounterStatistic
|
||||||
*/
|
*/
|
||||||
public long getCurrent()
|
public long getCurrent()
|
||||||
{
|
{
|
||||||
return _curr.get();
|
return _current.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
|
@ -120,13 +122,13 @@ public class CounterStatistic
|
||||||
*/
|
*/
|
||||||
public long getTotal()
|
public long getTotal()
|
||||||
{
|
{
|
||||||
return _total.get();
|
return _total.sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return String.format("%s@%x{c=%d,m=%d,t=%d}",this.getClass().getSimpleName(),hashCode(),_curr.get(),_max.get(),_total.get());
|
return String.format("%s@%x{c=%d,m=%d,t=%d}",this.getClass().getSimpleName(),hashCode(),_current.get(),_max.get(),_total.sum());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
package org.eclipse.jetty.util.statistic;
|
package org.eclipse.jetty.util.statistic;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
import java.util.concurrent.atomic.LongAccumulator;
|
||||||
|
import java.util.concurrent.atomic.LongAdder;
|
||||||
|
|
||||||
import org.eclipse.jetty.util.Atomics;
|
import org.eclipse.jetty.util.Atomics;
|
||||||
|
|
||||||
|
@ -30,7 +32,7 @@ import org.eclipse.jetty.util.Atomics;
|
||||||
* <p>
|
* <p>
|
||||||
* Calculates estimates of mean, variance, and standard deviation characteristics of a sample using a non synchronized
|
* Calculates estimates of mean, variance, and standard deviation characteristics of a sample using a non synchronized
|
||||||
* approximation of the on-line algorithm presented in <cite>Donald Knuth's Art of Computer Programming, Volume 2,
|
* approximation of the on-line algorithm presented in <cite>Donald Knuth's Art of Computer Programming, Volume 2,
|
||||||
* Seminumerical Algorithms, 3rd edition, page 232, Boston: Addison-Wesley</cite>. that cites a 1962 paper by B.P. Welford that
|
* Semi numerical Algorithms, 3rd edition, page 232, Boston: Addison-Wesley</cite>. that cites a 1962 paper by B.P. Welford that
|
||||||
* can be found by following <a href="http://www.jstor.org/pss/1266577">Note on a Method for Calculating Corrected Sums
|
* can be found by following <a href="http://www.jstor.org/pss/1266577">Note on a Method for Calculating Corrected Sums
|
||||||
* of Squares and Products</a>
|
* of Squares and Products</a>
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -40,17 +42,17 @@ import org.eclipse.jetty.util.Atomics;
|
||||||
*/
|
*/
|
||||||
public class SampleStatistic
|
public class SampleStatistic
|
||||||
{
|
{
|
||||||
protected final AtomicLong _max = new AtomicLong();
|
protected final LongAccumulator _max = new LongAccumulator(Math::max,0L);
|
||||||
protected final AtomicLong _total = new AtomicLong();
|
protected final AtomicLong _total = new AtomicLong();
|
||||||
protected final AtomicLong _count = new AtomicLong();
|
protected final AtomicLong _count = new AtomicLong();
|
||||||
protected final AtomicLong _totalVariance100 = new AtomicLong();
|
protected final LongAdder _totalVariance100 = new LongAdder();
|
||||||
|
|
||||||
public void reset()
|
public void reset()
|
||||||
{
|
{
|
||||||
_max.set(0);
|
_max.reset();
|
||||||
_total.set(0);
|
_total.set(0);
|
||||||
_count.set(0);
|
_count.set(0);
|
||||||
_totalVariance100.set(0);
|
_totalVariance100.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(final long sample)
|
public void set(final long sample)
|
||||||
|
@ -62,10 +64,10 @@ public class SampleStatistic
|
||||||
{
|
{
|
||||||
long mean10 = total*10/count;
|
long mean10 = total*10/count;
|
||||||
long delta10 = sample*10 - mean10;
|
long delta10 = sample*10 - mean10;
|
||||||
_totalVariance100.addAndGet(delta10*delta10);
|
_totalVariance100.add(delta10*delta10);
|
||||||
}
|
}
|
||||||
|
|
||||||
Atomics.updateMax(_max, sample);
|
_max.accumulate(sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,7 +95,7 @@ public class SampleStatistic
|
||||||
|
|
||||||
public double getVariance()
|
public double getVariance()
|
||||||
{
|
{
|
||||||
final long variance100 = _totalVariance100.get();
|
final long variance100 = _totalVariance100.sum();
|
||||||
final long count = _count.get();
|
final long count = _count.get();
|
||||||
|
|
||||||
return count>1?((double)variance100)/100.0/(count-1):0.0;
|
return count>1?((double)variance100)/100.0/(count-1):0.0;
|
||||||
|
@ -108,6 +110,6 @@ public class SampleStatistic
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return String.format("%s@%x{c=%d,m=%d,t=%d,v100=%d}",this.getClass().getSimpleName(),hashCode(),_count.get(),_max.get(),_total.get(),_totalVariance100.get());
|
return String.format("%s@%x{c=%d,m=%d,t=%d,v100=%d}",this.getClass().getSimpleName(),hashCode(),_count.get(),_max.get(),_total.get(),_totalVariance100.sum());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,13 +19,13 @@
|
||||||
package org.eclipse.jetty.util.statistic;
|
package org.eclipse.jetty.util.statistic;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.hamcrest.Matchers.greaterThan;
|
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||||
import static org.hamcrest.Matchers.lessThan;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
import org.hamcrest.Matchers;
|
import java.util.Random;
|
||||||
import org.junit.Assert;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.CyclicBarrier;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,4 +77,81 @@ public class CounterStatisticTest
|
||||||
assertThat(count.getTotal(),equalTo(5L));
|
assertThat(count.getTotal(),equalTo(5L));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCounterContended()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
final CounterStatistic counter = new CounterStatistic();
|
||||||
|
final int N=100;
|
||||||
|
final int L=1000;
|
||||||
|
final Thread[] threads = new Thread[N];
|
||||||
|
final CyclicBarrier incBarrier = new CyclicBarrier(N);
|
||||||
|
final CountDownLatch decBarrier = new CountDownLatch(N/2);
|
||||||
|
|
||||||
|
for (int i=N;i-->0;)
|
||||||
|
{
|
||||||
|
final int I = i;
|
||||||
|
|
||||||
|
|
||||||
|
threads[i]=(i>=N/2)
|
||||||
|
?new Thread()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
incBarrier.await();
|
||||||
|
decBarrier.await();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
Random random = new Random();
|
||||||
|
for (int l=L;l-->0;)
|
||||||
|
{
|
||||||
|
counter.decrement();
|
||||||
|
if (random.nextInt(5)==0)
|
||||||
|
Thread.yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:new Thread()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
incBarrier.await();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
Random random = new Random();
|
||||||
|
for (int l=L;l-->0;)
|
||||||
|
{
|
||||||
|
counter.increment();
|
||||||
|
if (l==L/2)
|
||||||
|
decBarrier.countDown();
|
||||||
|
if (random.nextInt(5)==0)
|
||||||
|
Thread.yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
threads[i].start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int i=N;i-->0;)
|
||||||
|
threads[i].join();
|
||||||
|
|
||||||
|
assertThat(counter.getCurrent(),equalTo(0L));
|
||||||
|
assertThat(counter.getTotal(),equalTo(N*L/2L));
|
||||||
|
assertThat(counter.getMax(),greaterThanOrEqualTo((N/2)*(L/2L)));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue