diff --git a/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java b/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java index 15ecc98457..7ee70e68ba 100644 --- a/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java +++ b/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java @@ -18,7 +18,7 @@ package com.alibaba.druid.stat; import java.util.Date; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicLongFieldUpdater; import javax.management.JMException; import javax.management.openmbean.ArrayType; @@ -38,70 +38,129 @@ import com.alibaba.druid.util.JMXUtils; */ public final class JdbcSqlStat implements JdbcSqlStatMBean { - private final String sql; - private long id; - private String dataSource; - private long executeLastStartTime; + private final String sql; + private long id; + private String dataSource; + private long executeLastStartTime; - private final AtomicLong executeBatchSizeTotal = new AtomicLong(); - private final AtomicLong executeBatchSizeMax = new AtomicLong(); + private volatile long executeBatchSizeTotal; + private volatile long executeBatchSizeMax; - private final AtomicLong executeSuccessCount = new AtomicLong(); - private final AtomicLong executeSpanNanoTotal = new AtomicLong(); - private final AtomicLong executeSpanNanoMax = new AtomicLong(); - private final AtomicLong runningCount = new AtomicLong(0L); - private final AtomicLong concurrentMax = new AtomicLong(); - private final AtomicLong resultSetHoldTimeNano = new AtomicLong(); - private final AtomicLong executeAndResultSetHoldTime = new AtomicLong(); + private volatile long executeSuccessCount; + private volatile long executeSpanNanoTotal; + private volatile long executeSpanNanoMax; + private volatile long runningCount; + private volatile long concurrentMax; + private volatile long resultSetHoldTimeNano; + private volatile long executeAndResultSetHoldTime; - private String name; - private String file; - private String dbType; + final static AtomicLongFieldUpdater executeBatchSizeTotalUpdater; + final static AtomicLongFieldUpdater executeBatchSizeMaxUpdater; + + final static AtomicLongFieldUpdater executeSuccessCountUpdater; + final static AtomicLongFieldUpdater executeSpanNanoTotalUpdater; + final static AtomicLongFieldUpdater executeSpanNanoMaxUpdater; + final static AtomicLongFieldUpdater runningCountUpdater; + final static AtomicLongFieldUpdater concurrentMaxUpdater; + final static AtomicLongFieldUpdater resultSetHoldTimeNanoUpdater; + final static AtomicLongFieldUpdater executeAndResultSetHoldTimeUpdater; + static { + executeBatchSizeTotalUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "executeBatchSizeTotal"); + executeBatchSizeMaxUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "executeBatchSizeMax"); + + executeSuccessCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "executeSuccessCount"); + executeSpanNanoTotalUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "executeSpanNanoTotal"); + executeSpanNanoMaxUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "executeSpanNanoMax"); + runningCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "runningCount"); + concurrentMaxUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "concurrentMax"); + resultSetHoldTimeNanoUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "resultSetHoldTimeNano"); + executeAndResultSetHoldTimeUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, + "executeAndResultSetHoldTime"); + } - private long executeNanoSpanMaxOccurTime; + private String name; + private String file; + private String dbType; - private final AtomicLong executeErrorCount = new AtomicLong(); - private Throwable executeErrorLast; - private long executeErrorLastTime; + private long executeNanoSpanMaxOccurTime; - private final AtomicLong updateCount = new AtomicLong(); - private final AtomicLong updateCountMax = new AtomicLong(); - private final AtomicLong fetchRowCount = new AtomicLong(); - private final AtomicLong fetchRowCountMax = new AtomicLong(); + private volatile long executeErrorCount; + private Throwable executeErrorLast; + private long executeErrorLastTime; - private final AtomicLong inTransactionCount = new AtomicLong(); + private volatile long updateCount; + private volatile long updateCountMax; + private volatile long fetchRowCount; + private volatile long fetchRowCountMax; - private String lastSlowParameters; + private volatile long inTransactionCount; - private boolean removed = false; + private String lastSlowParameters; - private final AtomicLong clobOpenCount = new AtomicLong(); - private final AtomicLong blobOpenCount = new AtomicLong(); - private final AtomicLong readStringLength = new AtomicLong(); - private final AtomicLong readBytesLength = new AtomicLong(); + private boolean removed = false; - private final AtomicLong inputStreamOpenCount = new AtomicLong(); - private final AtomicLong readerOpenCount = new AtomicLong(); + private volatile long clobOpenCount; + private volatile long blobOpenCount; + private volatile long readStringLength; + private volatile long readBytesLength; - private final Histogram histogram = new Histogram(new long[] { // - // + private volatile long inputStreamOpenCount; + private volatile long readerOpenCount; + + final static AtomicLongFieldUpdater executeErrorCountUpdater; + final static AtomicLongFieldUpdater updateCountUpdater; + final static AtomicLongFieldUpdater updateCountMaxUpdater; + final static AtomicLongFieldUpdater fetchRowCountUpdater; + final static AtomicLongFieldUpdater fetchRowCountMaxUpdater; + final static AtomicLongFieldUpdater inTransactionCountUpdater; + + final static AtomicLongFieldUpdater clobOpenCountUpdater; + final static AtomicLongFieldUpdater blobOpenCountUpdater; + final static AtomicLongFieldUpdater readStringLengthUpdater; + final static AtomicLongFieldUpdater readBytesLengthUpdater; + + final static AtomicLongFieldUpdater inputStreamOpenCountUpdater; + final static AtomicLongFieldUpdater readerOpenCountUpdater; + + static { + executeErrorCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "executeErrorCount"); + + updateCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "updateCount"); + updateCountMaxUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "updateCountMax"); + fetchRowCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "fetchRowCount"); + fetchRowCountMaxUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "fetchRowCountMax"); + inTransactionCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "inTransactionCount"); + + clobOpenCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "clobOpenCount"); + blobOpenCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "blobOpenCount"); + readStringLengthUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "readStringLength"); + readBytesLengthUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "readBytesLength"); + + inputStreamOpenCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "inputStreamOpenCount"); + readerOpenCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class, "readerOpenCount"); + } + + private final Histogram histogram = new Histogram(new long[] { // + // 1, 10, 100, 1000, 10 * 1000, // 100 * 1000, 1000 * 1000 - // - }); + // + }); - private final Histogram executeAndResultHoldTimeHistogram = new Histogram(new long[] { // - // + private final Histogram executeAndResultHoldTimeHistogram = new Histogram(new long[] { // + // 1, 10, 100, 1000, 10 * 1000, // 100 * 1000, 1000 * 1000 - // - }); + // + }); - private final Histogram fetchRowCountHistogram = new Histogram(new long[] { // - 1, 10, 100, 1000, 10 * 1000 }); + private final Histogram fetchRowCountHistogram = new Histogram(new long[] { // + 1, 10, 100, + 1000, 10 * 1000 }); - private final Histogram updateCountHistogram = new Histogram(new long[] { // - 1, 10, 100, 1000, 10 * 1000 }); + private final Histogram updateCountHistogram = new Histogram(new long[] { // + 1, 10, 100, + 1000, 10 * 1000 }); public JdbcSqlStat(String sql){ this.sql = sql; @@ -201,60 +260,60 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { public void reset() { executeLastStartTime = 0; - executeBatchSizeTotal.set(0); - executeBatchSizeMax.set(0); + executeBatchSizeTotalUpdater.set(this, 0); + executeBatchSizeMaxUpdater.set(this, 0); - executeSuccessCount.set(0); - executeSpanNanoTotal.set(0); - executeSpanNanoMax.set(0); + executeSuccessCountUpdater.set(this, 0); + executeSpanNanoTotalUpdater.set(this, 0); + executeSpanNanoMaxUpdater.set(this, 0); executeNanoSpanMaxOccurTime = 0; - runningCount.set(0); - concurrentMax.set(0); + runningCountUpdater.set(this, 0); + concurrentMaxUpdater.set(this, 0); - executeErrorCount.set(0); + executeErrorCountUpdater.set(this, 0); executeErrorLast = null; executeErrorLastTime = 0; - updateCount.set(0); - updateCountMax.set(0); - fetchRowCount.set(0); - fetchRowCountMax.set(0); + updateCountUpdater.set(this, 0); + updateCountMaxUpdater.set(this, 0); + fetchRowCountUpdater.set(this, 0); + fetchRowCountMaxUpdater.set(this, 0); histogram.reset(); this.lastSlowParameters = null; - inTransactionCount.set(0); - resultSetHoldTimeNano.set(0); - executeAndResultSetHoldTime.set(0); + inTransactionCountUpdater.set(this, 0); + resultSetHoldTimeNanoUpdater.set(this, 0); + executeAndResultSetHoldTimeUpdater.set(this, 0); fetchRowCountHistogram.reset(); updateCountHistogram.reset(); executeAndResultHoldTimeHistogram.reset(); - blobOpenCount.set(0); - clobOpenCount.set(0); - readStringLength.set(0); - readBytesLength.set(0); - inputStreamOpenCount.set(0); - readerOpenCount.set(0); + blobOpenCountUpdater.set(this, 0); + clobOpenCountUpdater.set(this, 0); + readStringLengthUpdater.set(this, 0); + readBytesLengthUpdater.set(this, 0); + inputStreamOpenCountUpdater.set(this, 0); + readerOpenCountUpdater.set(this, 0); } public long getConcurrentMax() { - return concurrentMax.get(); + return concurrentMax; } public long getRunningCount() { - return runningCount.get(); + return runningCount; } public void addUpdateCount(int delta) { if (delta > 0) { - this.updateCount.addAndGet(delta); + updateCountUpdater.addAndGet(this, delta); } for (;;) { - long max = updateCountMax.get(); + long max = updateCountMaxUpdater.get(this); if (delta <= max) { break; } - if (updateCountMax.compareAndSet(max, delta)) { + if (updateCountMaxUpdater.compareAndSet(this, max, delta)) { break; } } @@ -263,67 +322,67 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { } public long getUpdateCount() { - return updateCount.get(); + return updateCount; } public long getUpdateCountMax() { - return updateCountMax.get(); + return updateCountMax; } public long getFetchRowCount() { - return fetchRowCount.get(); + return fetchRowCount; } public long getFetchRowCountMax() { - return fetchRowCountMax.get(); + return fetchRowCountMax; } public long getClobOpenCount() { - return clobOpenCount.get(); + return clobOpenCount; } public void incrementClobOpenCount() { - clobOpenCount.incrementAndGet(); + clobOpenCountUpdater.incrementAndGet(this); } public long getBlobOpenCount() { - return blobOpenCount.get(); + return blobOpenCount; } public void incrementBlobOpenCount() { - blobOpenCount.incrementAndGet(); + blobOpenCountUpdater.incrementAndGet(this); } public long getReadStringLength() { - return readStringLength.get(); + return readStringLength; } public void addStringReadLength(long length) { - this.readStringLength.addAndGet(length); + readStringLengthUpdater.addAndGet(this, length); } public long getReadBytesLength() { - return readBytesLength.get(); + return readBytesLength; } public void addReadBytesLength(long length) { - this.readBytesLength.addAndGet(length); + readBytesLengthUpdater.addAndGet(this, length); } public long getReaderOpenCount() { - return readerOpenCount.get(); + return readerOpenCount; } public void addReaderOpenCount(int count) { - this.readerOpenCount.addAndGet(count); + readerOpenCountUpdater.addAndGet(this, count); } public long getInputStreamOpenCount() { - return inputStreamOpenCount.get(); + return inputStreamOpenCount; } public void addInputStreamOpenCount(int count) { - this.inputStreamOpenCount.addAndGet(count); + inputStreamOpenCountUpdater.addAndGet(this, count); } public long getId() { @@ -365,13 +424,13 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { } public void addFetchRowCount(long delta) { - this.fetchRowCount.addAndGet(delta); + fetchRowCountUpdater.addAndGet(this, delta); for (;;) { - long max = fetchRowCountMax.get(); + long max = fetchRowCountMaxUpdater.get(this); if (delta <= max) { break; } - if (fetchRowCountMax.compareAndSet(max, delta)) { + if (fetchRowCountMaxUpdater.compareAndSet(this, max, delta)) { break; } } @@ -380,13 +439,13 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { } public void addExecuteBatchCount(long batchSize) { - executeBatchSizeTotal.addAndGet(batchSize); + executeBatchSizeTotalUpdater.addAndGet(this, batchSize); // executeBatchSizeMax for (;;) { - long current = executeBatchSizeMax.get(); + long current = executeBatchSizeMaxUpdater.get(this); if (current < batchSize) { - if (executeBatchSizeMax.compareAndSet(current, batchSize)) { + if (executeBatchSizeMaxUpdater.compareAndSet(this, current, batchSize)) { break; } else { continue; @@ -398,20 +457,20 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { } public long getExecuteBatchSizeTotal() { - return executeBatchSizeTotal.get(); + return executeBatchSizeTotal; } public void incrementExecuteSuccessCount() { - executeSuccessCount.incrementAndGet(); + executeSuccessCountUpdater.incrementAndGet(this); } public void incrementRunningCount() { - long val = runningCount.incrementAndGet(); + long val = runningCountUpdater.incrementAndGet(this); for (;;) { - long max = concurrentMax.get(); + long max = concurrentMaxUpdater.get(this); if (val > max) { - if (concurrentMax.compareAndSet(max, val)) { + if (concurrentMaxUpdater.compareAndSet(this, max, val)) { break; } else { continue; @@ -423,15 +482,15 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { } public void decrementRunningCount() { - runningCount.decrementAndGet(); + runningCountUpdater.decrementAndGet(this); } public void decrementExecutingCount() { - runningCount.decrementAndGet(); + runningCountUpdater.decrementAndGet(this); } public long getExecuteSuccessCount() { - return executeSuccessCount.get(); + return executeSuccessCount; } public void addExecuteTime(StatementExecuteType executeType, boolean firstResultSet, long nanoSpan) { @@ -443,12 +502,12 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { } public void addExecuteTime(long nanoSpan) { - executeSpanNanoTotal.addAndGet(nanoSpan); + executeSpanNanoTotalUpdater.addAndGet(this, nanoSpan); for (;;) { - long current = executeSpanNanoMax.get(); + long current = executeSpanNanoMaxUpdater.get(this); if (current < nanoSpan) { - if (executeSpanNanoMax.compareAndSet(current, nanoSpan)) { + if (executeSpanNanoMaxUpdater.compareAndSet(this, current, nanoSpan)) { // 可能不准确,但是绝大多数情况下都会正确,性能换取一致性 executeNanoSpanMaxOccurTime = System.currentTimeMillis(); @@ -466,28 +525,28 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { } public long getExecuteMillisTotal() { - return executeSpanNanoTotal.get() / (1000 * 1000); + return executeSpanNanoTotal / (1000 * 1000); } public long getExecuteMillisMax() { - return executeSpanNanoMax.get() / (1000 * 1000); + return executeSpanNanoMax / (1000 * 1000); } public long getErrorCount() { - return executeErrorCount.get(); + return executeErrorCount; } @Override public long getExecuteBatchSizeMax() { - return executeBatchSizeMax.get(); + return executeBatchSizeMax; } public long getInTransactionCount() { - return inTransactionCount.get(); + return inTransactionCount; } public void incrementInTransactionCount() { - inTransactionCount.incrementAndGet(); + inTransactionCountUpdater.incrementAndGet(this); } private static CompositeType COMPOSITE_TYPE = null; @@ -710,7 +769,7 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { } public void error(Throwable error) { - executeErrorCount.incrementAndGet(); + executeErrorCountUpdater.incrementAndGet(this); executeErrorLastTime = System.currentTimeMillis(); executeErrorLast = error; @@ -737,20 +796,20 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { } public long getResultSetHoldTimeNano() { - return resultSetHoldTimeNano.get(); + return resultSetHoldTimeNano; } public long getExecuteAndResultSetHoldTimeNano() { - return executeAndResultSetHoldTime.get(); + return executeAndResultSetHoldTime; } public void addResultSetHoldTimeNano(long nano) { - resultSetHoldTimeNano.addAndGet(nano); + resultSetHoldTimeNanoUpdater.addAndGet(this, nano); } public void addResultSetHoldTimeNano(long statementExecuteNano, long resultHoldTimeNano) { - resultSetHoldTimeNano.addAndGet(resultHoldTimeNano); - executeAndResultSetHoldTime.addAndGet(statementExecuteNano + resultHoldTimeNano); + resultSetHoldTimeNanoUpdater.addAndGet(this, resultHoldTimeNano); + executeAndResultSetHoldTimeUpdater.addAndGet(this, statementExecuteNano + resultHoldTimeNano); executeAndResultHoldTimeHistogram.record((statementExecuteNano + resultHoldTimeNano) / 1000 / 1000); updateCountHistogram.record(0); } diff --git a/src/main/java/com/alibaba/druid/support/http/stat/WebSessionStat.java b/src/main/java/com/alibaba/druid/support/http/stat/WebSessionStat.java index 3ad9056484..320207bb6c 100644 --- a/src/main/java/com/alibaba/druid/support/http/stat/WebSessionStat.java +++ b/src/main/java/com/alibaba/druid/support/http/stat/WebSessionStat.java @@ -20,39 +20,63 @@ import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +import java.util.concurrent.atomic.AtomicLongFieldUpdater; import com.alibaba.druid.util.Histogram; public class WebSessionStat { - private final String sessionId; + private final String sessionId; - private final AtomicInteger runningCount = new AtomicInteger(); - private final AtomicInteger concurrentMax = new AtomicInteger(); - private final AtomicLong requestCount = new AtomicLong(0); - private final AtomicLong requestErrorCount = new AtomicLong(0); - private final AtomicLong requestTimeNano = new AtomicLong(); + private volatile int runningCount; + private volatile int concurrentMax; + final static AtomicIntegerFieldUpdater runningCountUpdater = AtomicIntegerFieldUpdater.newUpdater(WebSessionStat.class, + "runningCount"); + final static AtomicIntegerFieldUpdater concurrentMaxUpdater = AtomicIntegerFieldUpdater.newUpdater(WebSessionStat.class, + "concurrentMax"); - private final AtomicLong jdbcFetchRowCount = new AtomicLong(); - private final AtomicLong jdbcUpdateCount = new AtomicLong(); - private final AtomicLong jdbcExecuteCount = new AtomicLong(); - private final AtomicLong jdbcExecuteTimeNano = new AtomicLong(); + private volatile long requestCount; + private volatile long requestErrorCount; + private volatile long requestTimeNano; - private final AtomicLong jdbcCommitCount = new AtomicLong(); - private final AtomicLong jdbcRollbackCount = new AtomicLong(); + final static AtomicLongFieldUpdater requestCountUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class, + "requestCount"); + final static AtomicLongFieldUpdater requestErrorCountUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class, + "requestErrorCount"); + final static AtomicLongFieldUpdater requestTimeNanoUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class, + "requestTimeNano"); - private long createTimeMillis = -1L; - private volatile long lastAccessTimeMillis = -1L; + private volatile long jdbcFetchRowCount; + private volatile long jdbcUpdateCount; + private volatile long jdbcExecuteCount; + private volatile long jdbcExecuteTimeNano; + final static AtomicLongFieldUpdater jdbcFetchRowCountUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class, + "jdbcFetchRowCount"); + final static AtomicLongFieldUpdater jdbcUpdateCountUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class, + "jdbcUpdateCount"); + final static AtomicLongFieldUpdater jdbcExecuteCountUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class, + "jdbcExecuteCount"); + final static AtomicLongFieldUpdater jdbcExecuteTimeNanoUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class, + "jdbcExecuteTimeNano"); - private Set remoteAddresses = new HashSet(); + private volatile long jdbcCommitCount; + private volatile long jdbcRollbackCount; + final static AtomicLongFieldUpdater jdbcCommitCountUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class, + "jdbcCommitCount"); + final static AtomicLongFieldUpdater jdbcRollbackCountUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class, + "jdbcRollbackCount"); - private String principal = null; + private long createTimeMillis = -1L; + private volatile long lastAccessTimeMillis = -1L; - private String userAgent; + private Set remoteAddresses = new HashSet(2); - private Histogram requestIntervalHistogram = Histogram.makeHistogram(8); + private String principal = null; + + private String userAgent; + + private Histogram requestIntervalHistogram = Histogram.makeHistogram(8); public WebSessionStat(String sessionId){ super(); @@ -60,17 +84,17 @@ public class WebSessionStat { } public void reset() { - concurrentMax.set(0); - requestCount.set(0); - requestErrorCount.set(0); - requestTimeNano.set(0); + concurrentMaxUpdater.set(this, 0); + requestCountUpdater.set(this, 0); + requestErrorCountUpdater.set(this, 0); + requestTimeNanoUpdater.set(this, 0); - jdbcFetchRowCount.set(0); - jdbcUpdateCount.set(0); - jdbcExecuteCount.set(0); - jdbcExecuteTimeNano.set(0); - jdbcCommitCount.set(0); - jdbcRollbackCount.set(0); + jdbcFetchRowCountUpdater.set(this, 0); + jdbcUpdateCountUpdater.set(this, 0); + jdbcExecuteCountUpdater.set(this, 0); + jdbcExecuteTimeNanoUpdater.set(this, 0); + jdbcCommitCountUpdater.set(this, 0); + jdbcRollbackCountUpdater.set(this, 0); remoteAddresses.clear(); principal = null; @@ -159,12 +183,12 @@ public class WebSessionStat { } public void beforeInvoke() { - int running = runningCount.incrementAndGet(); + int running = runningCountUpdater.incrementAndGet(this); for (;;) { - int max = concurrentMax.get(); + int max = concurrentMaxUpdater.get(this); if (running > max) { - if (concurrentMax.compareAndSet(max, running)) { + if (concurrentMaxUpdater.compareAndSet(this, max, running)) { break; } else { continue; @@ -183,16 +207,16 @@ public class WebSessionStat { } public void incrementRequestCount() { - requestCount.incrementAndGet(); + requestCountUpdater.incrementAndGet(this); } public void afterInvoke(Throwable error, long nanos) { - runningCount.decrementAndGet(); + runningCountUpdater.decrementAndGet(this); reacord(nanos); } public void reacord(long nanos) { - requestTimeNano.addAndGet(nanos); + requestTimeNanoUpdater.addAndGet(this, nanos); WebRequestStat requestStat = WebRequestStat.current(); if (requestStat != null) { @@ -210,23 +234,23 @@ public class WebSessionStat { } public int getRunningCount() { - return this.runningCount.get(); + return this.runningCount; } public long getConcurrentMax() { - return concurrentMax.get(); + return concurrentMax; } public long getRequestCount() { - return requestCount.get(); + return requestCount; } public long getRequestErrorCount() { - return requestErrorCount.get(); + return requestErrorCount; } public long getRequestTimeNano() { - return requestTimeNano.get(); + return requestTimeNano; } public long getRequestTimeMillis() { @@ -234,31 +258,31 @@ public class WebSessionStat { } public void addJdbcFetchRowCount(long delta) { - this.jdbcFetchRowCount.addAndGet(delta); + jdbcFetchRowCountUpdater.addAndGet(this, delta); } public long getJdbcFetchRowCount() { - return jdbcFetchRowCount.get(); + return jdbcFetchRowCount; } public void addJdbcUpdateCount(long updateCount) { - this.jdbcUpdateCount.addAndGet(updateCount); + jdbcUpdateCountUpdater.addAndGet(this, updateCount); } public long getJdbcUpdateCount() { - return jdbcUpdateCount.get(); + return jdbcUpdateCount; } public void incrementJdbcExecuteCount() { - jdbcExecuteCount.incrementAndGet(); + jdbcExecuteCountUpdater.incrementAndGet(this); } public void addJdbcExecuteCount(long executeCount) { - jdbcExecuteCount.addAndGet(executeCount); + jdbcExecuteCountUpdater.addAndGet(this, executeCount); } public long getJdbcExecuteCount() { - return jdbcExecuteCount.get(); + return jdbcExecuteCount; } public long getJdbcExecuteTimeMillis() { @@ -266,35 +290,35 @@ public class WebSessionStat { } public long getJdbcExecuteTimeNano() { - return jdbcExecuteTimeNano.get(); + return jdbcExecuteTimeNano; } public void addJdbcExecuteTimeNano(long nano) { - jdbcExecuteTimeNano.addAndGet(nano); + jdbcExecuteTimeNanoUpdater.addAndGet(this, nano); } public void incrementJdbcCommitCount() { - jdbcCommitCount.incrementAndGet(); + jdbcCommitCountUpdater.incrementAndGet(this); } public long getJdbcCommitCount() { - return jdbcCommitCount.get(); + return jdbcCommitCount; } public void addJdbcCommitCount(long commitCount) { - this.jdbcCommitCount.addAndGet(commitCount); + jdbcCommitCountUpdater.addAndGet(this, commitCount); } public void incrementJdbcRollbackCount() { - jdbcRollbackCount.incrementAndGet(); + jdbcRollbackCountUpdater.incrementAndGet(this); } public long getJdbcRollbackCount() { - return jdbcRollbackCount.get(); + return jdbcRollbackCount; } public void addJdbcRollbackCount(long rollbackCount) { - this.jdbcRollbackCount.addAndGet(rollbackCount); + jdbcRollbackCountUpdater.addAndGet(this, rollbackCount); } public long[] getRequestInterval() { diff --git a/src/main/java/com/alibaba/druid/support/http/stat/WebURIStat.java b/src/main/java/com/alibaba/druid/support/http/stat/WebURIStat.java index fffd2fa481..c41b97b949 100644 --- a/src/main/java/com/alibaba/druid/support/http/stat/WebURIStat.java +++ b/src/main/java/com/alibaba/druid/support/http/stat/WebURIStat.java @@ -18,48 +18,93 @@ package com.alibaba.druid.support.http.stat; import java.util.Date; import java.util.LinkedHashMap; import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +import java.util.concurrent.atomic.AtomicLongFieldUpdater; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import com.alibaba.druid.support.profile.ProfileStat; import com.alibaba.druid.support.profile.Profiler; public class WebURIStat { - private final String uri; + private final String uri; - private final AtomicInteger runningCount = new AtomicInteger(); - private final AtomicInteger concurrentMax = new AtomicInteger(); - private final AtomicLong requestCount = new AtomicLong(0); - private final AtomicLong requestTimeNano = new AtomicLong(); + private volatile int runningCount; + private volatile int concurrentMax; + private volatile long requestCount; + private volatile long requestTimeNano; + final static AtomicIntegerFieldUpdater runningCountUpdater = AtomicIntegerFieldUpdater.newUpdater(WebURIStat.class, + "runningCount"); + final static AtomicIntegerFieldUpdater concurrentMaxUpdater = AtomicIntegerFieldUpdater.newUpdater(WebURIStat.class, + "concurrentMax"); + final static AtomicLongFieldUpdater requestCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "requestCount"); + final static AtomicLongFieldUpdater requestTimeNanoUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "requestTimeNano"); - private final AtomicLong jdbcFetchRowCount = new AtomicLong(); - private final AtomicLong jdbcFetchRowPeak = new AtomicLong(); // 单次请求读取行数的峰值 + private volatile long jdbcFetchRowCount; + private volatile long jdbcFetchRowPeak; // 单次请求读取行数的峰值 + final static AtomicLongFieldUpdater jdbcFetchRowCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "jdbcFetchRowCount"); + final static AtomicLongFieldUpdater jdbcFetchRowPeakUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "jdbcFetchRowPeak"); - private final AtomicLong jdbcUpdateCount = new AtomicLong(); - private final AtomicLong jdbcUpdatePeak = new AtomicLong(); // 单次请求更新行数的峰值 + private volatile long jdbcUpdateCount; + private volatile long jdbcUpdatePeak; // 单次请求更新行数的峰值 + final static AtomicLongFieldUpdater jdbcUpdateCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "jdbcUpdateCount"); + final static AtomicLongFieldUpdater jdbcUpdatePeakUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "jdbcUpdatePeak"); - private final AtomicLong jdbcExecuteCount = new AtomicLong(); - private final AtomicLong jdbcExecuteErrorCount = new AtomicLong(); - private final AtomicLong jdbcExecutePeak = new AtomicLong(); // 单次请求执行SQL次数的峰值 - private final AtomicLong jdbcExecuteTimeNano = new AtomicLong(); + private volatile long jdbcExecuteCount; + private volatile long jdbcExecuteErrorCount; + private volatile long jdbcExecutePeak; // 单次请求执行SQL次数的峰值 + private volatile long jdbcExecuteTimeNano; + final static AtomicLongFieldUpdater jdbcExecuteCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "jdbcExecuteCount"); + final static AtomicLongFieldUpdater jdbcExecuteErrorCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "jdbcExecuteErrorCount"); + final static AtomicLongFieldUpdater jdbcExecutePeakUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "jdbcExecutePeak"); + final static AtomicLongFieldUpdater jdbcExecuteTimeNanoUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "jdbcExecuteTimeNano"); - private final AtomicLong jdbcCommitCount = new AtomicLong(); - private final AtomicLong jdbcRollbackCount = new AtomicLong(); + private volatile long jdbcCommitCount; + private volatile long jdbcRollbackCount; + final static AtomicLongFieldUpdater jdbcCommitCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "jdbcCommitCount"); + final static AtomicLongFieldUpdater jdbcRollbackCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "jdbcRollbackCount"); - private final AtomicLong jdbcPoolConnectionOpenCount = new AtomicLong(); - private final AtomicLong jdbcPoolConnectionCloseCount = new AtomicLong(); + private volatile long jdbcPoolConnectionOpenCount; + private volatile long jdbcPoolConnectionCloseCount; + final static AtomicLongFieldUpdater jdbcPoolConnectionOpenCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "jdbcPoolConnectionOpenCount"); + final static AtomicLongFieldUpdater jdbcPoolConnectionCloseCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "jdbcPoolConnectionCloseCount"); - private final AtomicLong jdbcResultSetOpenCount = new AtomicLong(); - private final AtomicLong jdbcResultSetCloseCount = new AtomicLong(); + private volatile long jdbcResultSetOpenCount; + private volatile long jdbcResultSetCloseCount; - private final AtomicLong errorCount = new AtomicLong(); + private volatile long errorCount; - private volatile long lastAccessTimeMillis = -1L; + private volatile long lastAccessTimeMillis = -1L; - private ProfileStat profiletat = new ProfileStat(); + private volatile ProfileStat profiletat; - private final static ThreadLocal currentLocal = new ThreadLocal(); + final static AtomicLongFieldUpdater jdbcResultSetOpenCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "jdbcResultSetOpenCount"); + final static AtomicLongFieldUpdater jdbcResultSetCloseCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "jdbcResultSetCloseCount"); + final static AtomicLongFieldUpdater errorCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class, + "errorCount"); + final static AtomicReferenceFieldUpdater profiletatUpdater; + + static { + profiletatUpdater = AtomicReferenceFieldUpdater.newUpdater(WebURIStat.class, ProfileStat.class, "profiletat"); + } + + private final static ThreadLocal currentLocal = new ThreadLocal(); public WebURIStat(String uri){ super(); @@ -77,12 +122,12 @@ public class WebURIStat { public void beforeInvoke() { currentLocal.set(this); - int running = runningCount.incrementAndGet(); + int running = runningCountUpdater.incrementAndGet(this); for (;;) { - int max = concurrentMax.get(); + int max = concurrentMaxUpdater.get(this); if (running > max) { - if (concurrentMax.compareAndSet(max, running)) { + if (concurrentMaxUpdater.compareAndSet(this, max, running)) { break; } else { continue; @@ -92,7 +137,7 @@ public class WebURIStat { } } - requestCount.incrementAndGet(); + requestCountUpdater.incrementAndGet(this); WebRequestStat requestStat = WebRequestStat.current(); if (requestStat != null) { @@ -103,11 +148,11 @@ public class WebURIStat { } public void afterInvoke(Throwable error, long nanos) { - runningCount.decrementAndGet(); - requestTimeNano.addAndGet(nanos); + runningCountUpdater.decrementAndGet(this); + requestTimeNanoUpdater.addAndGet(this, nanos); if (error != null) { - errorCount.incrementAndGet(); + errorCountUpdater.incrementAndGet(this); } { @@ -118,12 +163,12 @@ public class WebURIStat { this.addJdbcFetchRowCount(fetchRowCount); for (;;) { - long peak = jdbcFetchRowPeak.get(); + long peak = jdbcFetchRowPeakUpdater.get(this); if (fetchRowCount <= peak) { break; } - if (jdbcFetchRowPeak.compareAndSet(peak, fetchRowCount)) { + if (jdbcFetchRowPeakUpdater.compareAndSet(this, peak, fetchRowCount)) { break; } } @@ -133,12 +178,12 @@ public class WebURIStat { this.addJdbcExecuteCount(executeCount); for (;;) { - long peak = jdbcExecutePeak.get(); + long peak = jdbcExecutePeakUpdater.get(this); if (executeCount <= peak) { break; } - if (jdbcExecutePeak.compareAndSet(peak, executeCount)) { + if (jdbcExecutePeakUpdater.compareAndSet(this, peak, executeCount)) { break; } } @@ -148,19 +193,19 @@ public class WebURIStat { this.addJdbcUpdateCount(updateCount); for (;;) { - long peak = jdbcUpdatePeak.get(); + long peak = jdbcUpdatePeakUpdater.get(this); if (updateCount <= peak) { break; } - if (jdbcUpdatePeak.compareAndSet(peak, updateCount)) { + if (jdbcUpdatePeakUpdater.compareAndSet(this, peak, updateCount)) { break; } } } - this.jdbcExecuteErrorCount.addAndGet(localStat.getJdbcExecuteErrorCount()); - this.jdbcExecuteTimeNano.addAndGet(localStat.getJdbcExecuteTimeNano()); + jdbcExecuteErrorCountUpdater.addAndGet(this, localStat.getJdbcExecuteErrorCount()); + jdbcExecuteTimeNanoUpdater.addAndGet(this, localStat.getJdbcExecuteTimeNano()); this.addJdbcPoolConnectionOpenCount(localStat.getJdbcPoolConnectionOpenCount()); this.addJdbcPoolConnectionCloseCount(localStat.getJdbcPoolConnectionCloseCount()); @@ -176,19 +221,19 @@ public class WebURIStat { } public int getRunningCount() { - return this.runningCount.get(); + return this.runningCount; } public long getConcurrentMax() { - return concurrentMax.get(); + return concurrentMax; } public long getRequestCount() { - return requestCount.get(); + return requestCount; } public long getRequestTimeNano() { - return requestTimeNano.get(); + return requestTimeNano; } public long getRequestTimeMillis() { @@ -196,47 +241,47 @@ public class WebURIStat { } public void addJdbcFetchRowCount(long delta) { - this.jdbcFetchRowCount.addAndGet(delta); + jdbcFetchRowCountUpdater.addAndGet(this, delta); } public long getJdbcFetchRowCount() { - return jdbcFetchRowCount.get(); + return jdbcFetchRowCount; } public long getJdbcFetchRowPeak() { - return jdbcFetchRowPeak.get(); + return jdbcFetchRowPeak; } public void addJdbcUpdateCount(long updateCount) { - this.jdbcUpdateCount.addAndGet(updateCount); + jdbcUpdateCountUpdater.addAndGet(this, updateCount); } public long getJdbcUpdateCount() { - return jdbcUpdateCount.get(); + return jdbcUpdateCount; } public long getJdbcUpdatePeak() { - return jdbcUpdatePeak.get(); + return jdbcUpdatePeak; } public void incrementJdbcExecuteCount() { - jdbcExecuteCount.incrementAndGet(); + jdbcExecuteCountUpdater.incrementAndGet(this); } public void addJdbcExecuteCount(long executeCount) { - jdbcExecuteCount.addAndGet(executeCount); + jdbcExecuteCountUpdater.addAndGet(this, executeCount); } public long getJdbcExecuteCount() { - return jdbcExecuteCount.get(); + return jdbcExecuteCount; } - public AtomicLong getJdbcExecuteErrorCount() { + public long getJdbcExecuteErrorCount() { return jdbcExecuteErrorCount; } public long getJdbcExecutePeak() { - return jdbcExecutePeak.get(); + return jdbcExecutePeak; } public long getJdbcExecuteTimeMillis() { @@ -244,23 +289,23 @@ public class WebURIStat { } public long getJdbcExecuteTimeNano() { - return jdbcExecuteTimeNano.get(); + return jdbcExecuteTimeNano; } public void incrementJdbcCommitCount() { - jdbcCommitCount.incrementAndGet(); + jdbcCommitCountUpdater.incrementAndGet(this); } public long getJdbcCommitCount() { - return jdbcCommitCount.get(); + return jdbcCommitCount; } public void incrementJdbcRollbackCount() { - jdbcRollbackCount.incrementAndGet(); + jdbcRollbackCountUpdater.incrementAndGet(this); } public long getJdbcRollbackCount() { - return jdbcRollbackCount.get(); + return jdbcRollbackCount; } public void setLastAccessTimeMillis(long lastAccessTimeMillis) { @@ -280,50 +325,56 @@ public class WebURIStat { } public long getErrorCount() { - return errorCount.get(); + return errorCount; } public long getJdbcPoolConnectionOpenCount() { - return jdbcPoolConnectionOpenCount.get(); + return jdbcPoolConnectionOpenCount; } public void addJdbcPoolConnectionOpenCount(long delta) { - jdbcPoolConnectionOpenCount.addAndGet(delta); + jdbcPoolConnectionOpenCountUpdater.addAndGet(this, delta); } public void incrementJdbcPoolConnectionOpenCount() { - jdbcPoolConnectionOpenCount.incrementAndGet(); + jdbcPoolConnectionOpenCountUpdater.incrementAndGet(this); } public long getJdbcPoolConnectionCloseCount() { - return jdbcPoolConnectionCloseCount.get(); + return jdbcPoolConnectionCloseCount; } public void addJdbcPoolConnectionCloseCount(long delta) { - jdbcPoolConnectionCloseCount.addAndGet(delta); + jdbcPoolConnectionCloseCountUpdater.addAndGet(this, delta); } public void incrementJdbcPoolConnectionCloseCount() { - jdbcPoolConnectionCloseCount.incrementAndGet(); + jdbcPoolConnectionCloseCountUpdater.incrementAndGet(this); } public long getJdbcResultSetOpenCount() { - return jdbcResultSetOpenCount.get(); + return jdbcResultSetOpenCount; } public void addJdbcResultSetOpenCount(long delta) { - jdbcResultSetOpenCount.addAndGet(delta); + jdbcResultSetOpenCountUpdater.addAndGet(this, delta); } public long getJdbcResultSetCloseCount() { - return jdbcResultSetCloseCount.get(); + return jdbcResultSetCloseCount; } public void addJdbcResultSetCloseCount(long delta) { - jdbcResultSetCloseCount.addAndGet(delta); + jdbcResultSetCloseCountUpdater.addAndGet(this, delta); } public ProfileStat getProfiletat() { + if (profiletat != null) { + return profiletat; + } + + profiletatUpdater.compareAndSet(this, null, new ProfileStat()); + return profiletat; } diff --git a/src/test/java/com/alibaba/druid/stat/HistogramMemoryTest.java b/src/test/java/com/alibaba/druid/stat/HistogramMemoryTest.java index 8dd0d9ec83..4406215fa7 100644 --- a/src/test/java/com/alibaba/druid/stat/HistogramMemoryTest.java +++ b/src/test/java/com/alibaba/druid/stat/HistogramMemoryTest.java @@ -3,8 +3,6 @@ package com.alibaba.druid.stat; import java.lang.management.ManagementFactory; import java.text.NumberFormat; -import com.alibaba.druid.util.Histogram; - import junit.framework.TestCase; public class HistogramMemoryTest extends TestCase { @@ -15,8 +13,8 @@ public class HistogramMemoryTest extends TestCase { final int COUNT = 1024 * 1; Object[] items = new Object[COUNT]; for (int i = 0; i < COUNT; ++i) { - // items[i] = new JdbcSqlStat(""); - items[i] = Histogram.makeHistogram(20); + items[i] = new JdbcSqlStat(""); +// items[i] = Histogram.makeHistogram(20); } long memoryEnd = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed();