More refactors to isolate metrics from internal pool classes

pull/427/head
Brett Wooldridge 10 years ago
parent eaa5ca879e
commit 3bb13c03db

@ -23,18 +23,15 @@ package com.zaxxer.hikari.metrics;
*/ */
public class MetricsTracker implements AutoCloseable public class MetricsTracker implements AutoCloseable
{ {
public static final MetricsTimerContext NO_CONTEXT = new MetricsTimerContext();
public MetricsTracker() public MetricsTracker()
{ {
} }
public MetricsTimerContext recordConnectionRequest() public void recordConnectionAcquireNanos(final long elapsedAcquireNano)
{ {
return NO_CONTEXT;
} }
public void recordConnectionUsage(final long elapsedLastBorrowed) public void recordConnectionUsageMillis(final long elapsedLastBorrowed)
{ {
} }
@ -42,19 +39,4 @@ public class MetricsTracker implements AutoCloseable
public void close() public void close()
{ {
} }
/**
* A base instance of a MetricsContext. Classes extending this class should exhibit the
* behavior of "starting" a timer upon construction, and "stopping" the timer when the
* {@link MetricsTimerContext#stop()} method is called.
*
* @author Brett Wooldridge
*/
public static class MetricsTimerContext
{
public void stop()
{
// do nothing
}
}
} }

@ -16,6 +16,8 @@
package com.zaxxer.hikari.metrics.dropwizard; package com.zaxxer.hikari.metrics.dropwizard;
import java.util.concurrent.TimeUnit;
import com.codahale.metrics.Gauge; import com.codahale.metrics.Gauge;
import com.codahale.metrics.Histogram; import com.codahale.metrics.Histogram;
import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.MetricRegistry;
@ -84,16 +86,16 @@ public final class CodaHaleMetricsTracker extends MetricsTracker
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public Context recordConnectionRequest() public void recordConnectionAcquireNanos(final long elapsedAcquireNanos)
{ {
return new Context(connectionObtainTimer); connectionObtainTimer.update(elapsedAcquireNanos, TimeUnit.NANOSECONDS);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void recordConnectionUsage(final long elapsedLastBorrowed) public void recordConnectionUsageMillis(final long elapsedBorrowedMilli)
{ {
connectionUsage.update(elapsedLastBorrowed); connectionUsage.update(elapsedBorrowedMilli);
} }
public Timer getConnectionAcquisitionTimer() public Timer getConnectionAcquisitionTimer()
@ -105,20 +107,4 @@ public final class CodaHaleMetricsTracker extends MetricsTracker
{ {
return connectionUsage; return connectionUsage;
} }
public static final class Context extends MetricsTimerContext
{
final Timer.Context innerContext;
Context(Timer timer) {
innerContext = timer.time();
}
/** {@inheritDoc} */
@Override
public void stop()
{
innerContext.stop();
}
}
} }

@ -43,8 +43,6 @@ import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.health.HealthCheckRegistry; import com.codahale.metrics.health.HealthCheckRegistry;
import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariPoolMXBean; import com.zaxxer.hikari.HikariPoolMXBean;
import com.zaxxer.hikari.metrics.MetricsTracker;
import com.zaxxer.hikari.metrics.MetricsTracker.MetricsTimerContext;
import com.zaxxer.hikari.metrics.MetricsTrackerFactory; import com.zaxxer.hikari.metrics.MetricsTrackerFactory;
import com.zaxxer.hikari.metrics.PoolStats; import com.zaxxer.hikari.metrics.PoolStats;
import com.zaxxer.hikari.metrics.dropwizard.CodahaleHealthChecker; import com.zaxxer.hikari.metrics.dropwizard.CodahaleHealthChecker;
@ -158,7 +156,6 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL
try { try {
long timeout = hardTimeout; long timeout = hardTimeout;
final MetricsTimerContext metricsContext = (isRecordMetrics ? metricsTracker.recordConnectionRequest() : MetricsTracker.NO_CONTEXT);
do { do {
final PoolEntry poolEntry = connectionBag.borrow(timeout, TimeUnit.MILLISECONDS); final PoolEntry poolEntry = connectionBag.borrow(timeout, TimeUnit.MILLISECONDS);
if (poolEntry == null) { if (poolEntry == null) {
@ -171,8 +168,7 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL
timeout = hardTimeout - clockSource.elapsedMillis(startTime, now); timeout = hardTimeout - clockSource.elapsedMillis(startTime, now);
} }
else { else {
metricsTracker.recordLastBurrowed(poolEntry, now); metricsTracker.recordBorrowStats(poolEntry, startTime);
metricsContext.stop();
return poolEntry.createProxyConnection(leakTask.start(poolEntry), now); return poolEntry.createProxyConnection(leakTask.start(poolEntry), now);
} }
} }

@ -23,7 +23,7 @@ import org.slf4j.LoggerFactory;
import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.metrics.MetricsTracker; import com.zaxxer.hikari.metrics.MetricsTracker;
import com.zaxxer.hikari.metrics.MetricsTracker.MetricsTimerContext; import com.zaxxer.hikari.util.ClockSource;
import com.zaxxer.hikari.util.DefaultThreadFactory; import com.zaxxer.hikari.util.DefaultThreadFactory;
import com.zaxxer.hikari.util.DriverDataSource; import com.zaxxer.hikari.util.DriverDataSource;
import com.zaxxer.hikari.util.PropertyElf; import com.zaxxer.hikari.util.PropertyElf;
@ -564,33 +564,26 @@ abstract class PoolBase
tracker.close(); tracker.close();
} }
MetricsTimerContext recordConnectionRequest()
{
return tracker.recordConnectionRequest();
}
void recordConnectionUsage(final PoolEntry poolEntry) void recordConnectionUsage(final PoolEntry poolEntry)
{ {
tracker.recordConnectionUsage(poolEntry.getElapsedLastBorrowed()); tracker.recordConnectionUsageMillis(poolEntry.getElapsedLastBorrowed());
} }
/** /**
* @param poolEntry * @param poolEntry
* @param now * @param now
*/ */
void recordLastBurrowed(final PoolEntry poolEntry, final long now) void recordBorrowStats(final PoolEntry poolEntry, final long startTime)
{ {
final long now = ClockSource.INSTANCE.currentTime();
poolEntry.lastBorrowed = now; poolEntry.lastBorrowed = now;
tracker.recordConnectionAcquireNanos(ClockSource.INSTANCE.elapsedNanos(startTime, now));
} }
} }
static final class NopMetricsTrackerDelegate extends MetricsTrackerDelegate static final class NopMetricsTrackerDelegate extends MetricsTrackerDelegate
{ {
MetricsTimerContext recordConnectionRequest() @Override
{
return MetricsTracker.NO_CONTEXT;
}
void recordConnectionUsage(final PoolEntry poolEntry) void recordConnectionUsage(final PoolEntry poolEntry)
{ {
// no-op // no-op
@ -603,7 +596,7 @@ abstract class PoolBase
} }
@Override @Override
void recordLastBurrowed(final PoolEntry poolEntry, final long now) void recordBorrowStats(final PoolEntry poolEntry, final long startTime)
{ {
// no-op // no-op
} }

@ -63,6 +63,25 @@ public interface ClockSource
*/ */
long elapsedMillis(long startTime, long endTime); long elapsedMillis(long startTime, long endTime);
/**
* Convert an opaque time-stamp returned by currentTime() into an
* elapsed time in milliseconds, based on the current instant in time.
*
* @param startTime an opaque time-stamp returned by an instance of this class
* @return the elapsed time between startTime and now in milliseconds
*/
long elapsedNanos(long startTime);
/**
* Get the difference in nanoseconds between two opaque time-stamps returned
* by currentTime().
*
* @param startTime an opaque time-stamp returned by an instance of this class
* @param endTime an opaque time-stamp returned by an instance of this class
* @return the elapsed time between startTime and endTime in nanoseconds
*/
long elapsedNanos(long startTime, long endTime);
/** /**
* Return the specified opaque time-stamp plus the specified number of milliseconds. * Return the specified opaque time-stamp plus the specified number of milliseconds.
* *
@ -72,6 +91,12 @@ public interface ClockSource
*/ */
long plusMillis(long time, long millis); long plusMillis(long time, long millis);
/**
* Get the TimeUnit the ClockSource is denominated in.
* @return
*/
TimeUnit getSourceTimeUnit();
/** /**
* Factory class used to create a platform-specific ClockSource. * Factory class used to create a platform-specific ClockSource.
*/ */
@ -113,17 +138,38 @@ public interface ClockSource
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public long toMillis(long time) public long elapsedNanos(final long startTime)
{
return TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis() - startTime);
}
/** {@inheritDoc} */
@Override
public long elapsedNanos(final long startTime, final long endTime)
{
return TimeUnit.MILLISECONDS.toNanos(endTime - startTime);
}
/** {@inheritDoc} */
@Override
public long toMillis(final long time)
{ {
return time; return time;
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public long plusMillis(long time, long millis) public long plusMillis(final long time, final long millis)
{ {
return time + millis; return time + millis;
} }
/** {@inheritDoc} */
@Override
public TimeUnit getSourceTimeUnit()
{
return TimeUnit.MILLISECONDS;
}
} }
final class NanosecondClockSource implements ClockSource final class NanosecondClockSource implements ClockSource
@ -156,11 +202,32 @@ public interface ClockSource
return TimeUnit.NANOSECONDS.toMillis(endTime - startTime); return TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
} }
/** {@inheritDoc} */
@Override
public long elapsedNanos(final long startTime)
{
return System.nanoTime() - startTime;
}
/** {@inheritDoc} */
@Override
public long elapsedNanos(final long startTime, final long endTime)
{
return endTime - startTime;
}
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public long plusMillis(final long time, final long millis) public long plusMillis(final long time, final long millis)
{ {
return time + TimeUnit.MILLISECONDS.toNanos(millis); return time + TimeUnit.MILLISECONDS.toNanos(millis);
} }
/** {@inheritDoc} */
@Override
public TimeUnit getSourceTimeUnit()
{
return TimeUnit.NANOSECONDS;
}
} }
} }

@ -121,18 +121,16 @@ public class ConcurrentBag<T extends IConcurrentBagEntry> implements AutoCloseab
public T borrow(long timeout, final TimeUnit timeUnit) throws InterruptedException public T borrow(long timeout, final TimeUnit timeUnit) throws InterruptedException
{ {
// Try the thread-local list first, if there are no blocked threads waiting already // Try the thread-local list first, if there are no blocked threads waiting already
if (!synchronizer.hasQueuedThreads()) { List<?> list = threadList.get();
List<?> list = threadList.get(); if (weakThreadLocals && list == null) {
if (weakThreadLocals && list == null) { list = new ArrayList<>(16);
list = new ArrayList<>(16); threadList.set(list);
threadList.set(list); }
}
for (int i = list.size() - 1; i >= 0; i--) { for (int i = list.size() - 1; i >= 0; i--) {
final T bagEntry = (T) (weakThreadLocals ? ((WeakReference) list.remove(i)).get() : list.remove(i)); final T bagEntry = (T) (weakThreadLocals ? ((WeakReference) list.remove(i)).get() : list.remove(i));
if (bagEntry != null && bagEntry.compareAndSet(STATE_NOT_IN_USE, STATE_IN_USE)) { if (bagEntry != null && bagEntry.compareAndSet(STATE_NOT_IN_USE, STATE_IN_USE)) {
return bagEntry; return bagEntry;
}
} }
} }

Loading…
Cancel
Save