Issue #2288 - Cleanup the statistics classes. (#2290)

* Issue #2288 - Cleanup the statistics classes.

Cleaned up code, added Javadocs.
Renamed SampleStatistics.set(long) to record(long).

Signed-off-by: Simone Bordet <simone.bordet@gmail.com>

* toString stddev

Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
Simone Bordet 2018-03-07 22:35:21 +01:00 committed by Greg Wilkins
parent 5712b0217f
commit a3100e0211
7 changed files with 101 additions and 79 deletions

View File

@ -94,7 +94,7 @@ public class ConnectionStatistics extends AbstractLifeCycle implements Connectio
_connections.decrement();
long elapsed = System.currentTimeMillis() - connection.getCreatedTimeStamp();
_connectionsDuration.set(elapsed);
_connectionsDuration.record(elapsed);
long bytesIn = connection.getBytesIn();
if (bytesIn > 0)

View File

@ -80,10 +80,10 @@ public class ConnectorStatistics extends AbstractLifeCycle implements Dumpable,
{
long msgsIn=connection.getMessagesIn();
long msgsOut=connection.getMessagesOut();
_messagesIn.set(msgsIn);
_messagesOut.set(msgsOut);
_messagesIn.record(msgsIn);
_messagesOut.record(msgsOut);
_connectionStats.decrement();
_connectionDurationStats.set(System.currentTimeMillis()-connection.getCreatedTimeStamp());
_connectionDurationStats.record(System.currentTimeMillis()-connection.getCreatedTimeStamp());
Sample sample=_samples.remove(connection);
if (sample!=null)

View File

@ -102,7 +102,7 @@ public class StatisticsHandler extends HandlerWrapper implements Graceful
final long elapsed = System.currentTimeMillis()-request.getTimeStamp();
long d=_requestStats.decrement();
_requestTimeStats.set(elapsed);
_requestTimeStats.record(elapsed);
updateResponse(request);
@ -184,7 +184,7 @@ public class StatisticsHandler extends HandlerWrapper implements Graceful
final long dispatched=now-start;
_dispatchedStats.decrement();
_dispatchedTimeStats.set(dispatched);
_dispatchedTimeStats.record(dispatched);
if (state.isSuspended())
{
@ -197,7 +197,7 @@ public class StatisticsHandler extends HandlerWrapper implements Graceful
else if (state.isInitial())
{
long d=_requestStats.decrement();
_requestTimeStats.set(dispatched);
_requestTimeStats.record(dispatched);
updateResponse(baseRequest);
// If we have no more dispatches, should we signal shutdown?

View File

@ -18,8 +18,6 @@
package org.eclipse.jetty.server.session;
import static java.lang.Math.round;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
@ -63,9 +61,11 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.statistic.CounterStatistic;
import org.eclipse.jetty.util.statistic.SampleStatistic;
import org.eclipse.jetty.util.thread.Locker.Lock;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import org.eclipse.jetty.util.thread.Scheduler;
import org.eclipse.jetty.util.thread.Locker.Lock;
import static java.lang.Math.round;
/* ------------------------------------------------------------ */
/**
@ -1235,7 +1235,7 @@ public class SessionHandler extends ScopedHandler
if (session != null)
{
_sessionTimeStats.set(round((System.currentTimeMillis() - session.getSessionData().getCreated())/1000.0));
_sessionTimeStats.record(round((System.currentTimeMillis() - session.getSessionData().getCreated())/1000.0));
session.finishInvalidate();
}
}

View File

@ -22,51 +22,53 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAccumulator;
import java.util.concurrent.atomic.LongAdder;
/* ------------------------------------------------------------ */
/** Statistics on a counter value.
* <p>
* Keep total, current and maximum values of a counter that
* can be incremented and decremented. The total refers only
* to increments.
*
/**
* <p>Statistics on a counter value.</p>
* <p>This class keeps the total, current and maximum value of a counter
* that can be incremented and decremented. The total refers only to increments.</p>
*/
public class CounterStatistic
{
protected final LongAccumulator _max = new LongAccumulator(Math::max,0L);
protected final AtomicLong _current = new AtomicLong();
protected final LongAdder _total = new LongAdder();
private final LongAccumulator _max = new LongAccumulator(Math::max, 0L);
private final AtomicLong _current = new AtomicLong();
private final LongAdder _total = new LongAdder();
/* ------------------------------------------------------------ */
/**
* Resets the max and total to the current value.
*/
public void reset()
{
_total.reset();
_max.reset();
long current=_current.get();
long current = _current.get();
_total.add(current);
_max.accumulate(current);
}
/* ------------------------------------------------------------ */
/**
* Resets the max, total and current value to the given parameter.
*
* @param value the new current value
*/
public void reset(final long value)
{
_current.set(value);
_total.reset();
_max.reset();
if (value>0)
if (value > 0)
{
_total.add(value);
_max.accumulate(value);
}
}
/* ------------------------------------------------------------ */
/**
* @param delta the amount to add to the count
* @return the new value
* @param delta the amount to add to the counter
* @return the new counter value
*/
public long add(final long delta)
{
long value=_current.addAndGet(delta);
long value = _current.addAndGet(delta);
if (delta > 0)
{
_total.add(delta);
@ -75,60 +77,56 @@ public class CounterStatistic
return value;
}
/* ------------------------------------------------------------ */
/**
* increment the value by one
* @return the new value, post increment
* Increments the value by one.
*
* @return the new counter value after the increment
*/
public long increment()
{
long value=_current.incrementAndGet();
long value = _current.incrementAndGet();
_total.increment();
_max.accumulate(value);
return value;
}
/* ------------------------------------------------------------ */
/**
* decrement by 1
* @return the new value, post-decrement
* Decrements the value by one.
*
* @return the new counter value after the decrement
*/
public long decrement()
{
return _current.decrementAndGet();
}
/* ------------------------------------------------------------ */
/**
* @return max value
* @return max counter value
*/
public long getMax()
{
return _max.get();
}
/* ------------------------------------------------------------ */
/**
* @return current value
* @return current counter value
*/
public long getCurrent()
{
return _current.get();
}
/* ------------------------------------------------------------ */
/**
* @return total value
* @return total counter value
*/
public long getTotal()
{
return _total.sum();
}
/* ------------------------------------------------------------ */
@Override
public String toString()
{
return String.format("%s@%x{c=%d,m=%d,t=%d}",this.getClass().getSimpleName(),hashCode(),_current.get(),_max.get(),_total.sum());
return String.format("%s@%x{c=%d,m=%d,t=%d}", getClass().getSimpleName(), hashCode(), getCurrent(), getMax(), getTotal());
}
}

View File

@ -22,31 +22,26 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAccumulator;
import java.util.concurrent.atomic.LongAdder;
import org.eclipse.jetty.util.Atomics;
/**
* SampledStatistics
* <p>
* Provides max, total, mean, count, variance, and standard deviation of continuous sequence of samples.
* <p>
* Calculates estimates of mean, variance, and standard deviation characteristics of a sample using a non synchronized
* <p>Statistics on a sampled value.</p>
* <p>Provides max, total, mean, count, variance, and standard deviation of continuous sequence of samples.</p>
* <p>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,
* 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
* of Squares and Products</a>
* <p>
* This algorithm is also described in Wikipedia at <a href=
* "http://en.wikipedia.org/w/index.php?title=Algorithms_for_calculating_variance&amp;section=4#On-line_algorithm">
* Algorithms for calculating variance </a>
* Semi numerical Algorithms, 3rd edition, page 232, Boston: Addison-Wesley</cite>. That cites a 1962 paper by B.P. Welford:
* <a href="http://www.jstor.org/pss/1266577">Note on a Method for Calculating Corrected Sums of Squares and Products</a></p>
* <p>This algorithm is also described in Wikipedia in the section "Online algorithm":
* <a href="https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance">Algorithms for calculating variance</a>.</p>
*/
public class SampleStatistic
{
protected final LongAccumulator _max = new LongAccumulator(Math::max,0L);
protected final AtomicLong _total = new AtomicLong();
protected final AtomicLong _count = new AtomicLong();
protected final LongAdder _totalVariance100 = new LongAdder();
private final LongAccumulator _max = new LongAccumulator(Math::max, 0L);
private final AtomicLong _total = new AtomicLong();
private final AtomicLong _count = new AtomicLong();
private final LongAdder _totalVariance100 = new LongAdder();
/**
* Resets the statistics.
*/
public void reset()
{
_max.reset();
@ -55,61 +50,89 @@ public class SampleStatistic
_totalVariance100.reset();
}
public void set(final long sample)
/**
* Records a sample value.
*
* @param sample the value to record.
*/
public void record(long sample)
{
long total = _total.addAndGet(sample);
long count = _count.incrementAndGet();
if (count>1)
if (count > 1)
{
long mean10 = total*10/count;
long delta10 = sample*10 - mean10;
_totalVariance100.add(delta10*delta10);
long mean10 = total * 10 / count;
long delta10 = sample * 10 - mean10;
_totalVariance100.add(delta10 * delta10);
}
_max.accumulate(sample);
}
/**
* @return the max value
* @deprecated use {@link #record(long)} instead
*/
@Deprecated
public void set(long sample)
{
record(sample);
}
/**
* @return the max value of the recorded samples
*/
public long getMax()
{
return _max.get();
}
/**
* @return the sum of all the recorded samples
*/
public long getTotal()
{
return _total.get();
}
/**
* @return the number of samples recorded
*/
public long getCount()
{
return _count.get();
}
/**
* @return the average value of the samples recorded, or zero if there are no samples
*/
public double getMean()
{
return (double)_total.get()/_count.get();
long count = getCount();
return count > 0 ? (double)_total.get() / _count.get() : 0.0D;
}
/**
* @return the variance of the samples recorded, or zero if there are less than 2 samples
*/
public double getVariance()
{
final long variance100 = _totalVariance100.sum();
final long count = _count.get();
return count>1?((double)variance100)/100.0/(count-1):0.0;
long variance100 = _totalVariance100.sum();
long count = getCount();
return count > 1 ? variance100 / 100.0D / (count - 1) : 0.0D;
}
/**
* @return the standard deviation of the samples recorded
*/
public double getStdDev()
{
return Math.sqrt(getVariance());
}
/* ------------------------------------------------------------ */
@Override
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.sum());
return String.format("%s@%x{count=%d,mean=%d,total=%d,stddev=%f}", getClass().getSimpleName(), hashCode(), getCount(), getMax(), getTotal(), getStdDev());
}
}

View File

@ -18,12 +18,12 @@
package org.eclipse.jetty.util.statistic;
import static org.junit.Assert.assertEquals;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/* ------------------------------------------------------------ */
public class SampleStatisticTest
@ -55,12 +55,13 @@ public class SampleStatisticTest
{
stats.reset();
for (long x : data[d])
stats.set(x);
stats.record(x);
assertEquals("count"+d,data[d].length, (int)stats.getCount());
assertNearEnough("mean"+d,results[d][0], stats.getMean());
assertNearEnough("stddev"+d,results[d][1], stats.getStdDev());
}
System.err.println(stats);
}
private void assertNearEnough(String test,double expected, double actual)