Author: amitj
Date: Mon Jun 25 10:42:16 2018
New Revision: 1834299
URL: http://svn.apache.org/viewvc?rev=1834299&view=rev
Log:
OAK-7584: Add stats for DataStore GC performance
Added stats for candidates found, blobs deleted, size deleted
Modified:
jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/MarkSweepGarbageCollector.java
jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/OperationStatsCollector.java
jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/BlobGCTest.java
Modified:
jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/MarkSweepGarbageCollector.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/MarkSweepGarbageCollector.java?rev=1834299&r1=1834298&r2=1834299&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/MarkSweepGarbageCollector.java
(original)
+++
jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/MarkSweepGarbageCollector.java
Mon Jun 25 10:42:16 2018
@@ -493,6 +493,10 @@ public class MarkSweepGarbageCollector i
org.apache.jackrabbit.oak.commons.IOUtils.humanReadableByteCount(deletedSize),
deletedSize);
}
+ statsCollector.updateNumCandidates(count);
+ statsCollector.updateNumDeleted(deleted);
+ statsCollector.updateTotalSizeDeleted(deletedSize);
+
// Remove all the merged marked references
GarbageCollectionType.get(blobStore).removeAllMarkedReferences(blobStore);
LOG.debug("Ending sweep phase of the garbage collector");
@@ -979,15 +983,21 @@ public class MarkSweepGarbageCollector i
}
class GarbageCollectionOperationStats implements OperationsStatsMBean {
- private static final String NAME = "DataStoreGarbageCollection";
- private static final String START = "COUNTER";
- private static final String FINISH_FAILURE = "FAILURE";
- private static final String DURATION = "ACTIVE_TIMER";
- private static final String MARK_DURATION = "MARK_TIMER";
- private static final String SWEEP_DURATION = "SWEEP_TIMER";
+ static final String NAME = "DataStoreGarbageCollection";
+ static final String START = "COUNTER";
+ static final String FINISH_FAILURE = "FAILURE";
+ static final String DURATION = "ACTIVE_TIMER";
+ static final String MARK_DURATION = "MARK_TIMER";
+ static final String SWEEP_DURATION = "SWEEP_TIMER";
+ static final String NUM_BLOBS_DELETED = "NUM_BLOBS_DELETED";
+ static final String TOTAL_SIZE_DELETED = "TOTAL_SIZE_DELETED";
+ static final String NUM_CANDIDATES = "NUM_CANDIDATES";
private CounterStats startCounter;
private CounterStats finishFailureCounter;
+ private CounterStats numDeletedCounter;
+ private CounterStats totalSizeDeletedCounter;
+ private CounterStats numCandidatesCounter;
private TimerStats duration;
private final TimerStats markDuration;
private final TimerStats sweepDuration;
@@ -996,6 +1006,9 @@ public class MarkSweepGarbageCollector i
GarbageCollectionOperationStats(StatisticsProvider sp) {
this.startCounter = sp.getCounterStats(getMetricName(START),
StatsOptions.METRICS_ONLY);
this.finishFailureCounter =
sp.getCounterStats(getMetricName(FINISH_FAILURE), StatsOptions.METRICS_ONLY);
+ this.numDeletedCounter =
sp.getCounterStats(getMetricName(NUM_BLOBS_DELETED), StatsOptions.METRICS_ONLY);
+ this.totalSizeDeletedCounter =
sp.getCounterStats(getMetricName(TOTAL_SIZE_DELETED),
StatsOptions.METRICS_ONLY);
+ this.numCandidatesCounter =
sp.getCounterStats(getMetricName(NUM_CANDIDATES), StatsOptions.METRICS_ONLY);
this.duration = sp.getTimer(getMetricName(DURATION),
StatsOptions.METRICS_ONLY);
this.markDuration = sp.getTimer(getMetricName(MARK_DURATION),
StatsOptions.METRICS_ONLY);
this.sweepDuration = sp.getTimer(getMetricName(SWEEP_DURATION),
StatsOptions.METRICS_ONLY);
@@ -1012,6 +1025,21 @@ public class MarkSweepGarbageCollector i
}
@Override
+ public void updateNumDeleted(long num) {
+ numDeletedCounter.inc(num);
+ }
+
+ @Override
+ public void updateNumCandidates(long num) {
+ numCandidatesCounter.inc(num);
+ }
+
+ @Override
+ public void updateTotalSizeDeleted(long size) {
+ totalSizeDeletedCounter.inc(size);
+ }
+
+ @Override
public void updateDuration(long time, TimeUnit timeUnit) {
duration.update(time, timeUnit);
}
Modified:
jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/OperationStatsCollector.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/OperationStatsCollector.java?rev=1834299&r1=1834298&r2=1834299&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/OperationStatsCollector.java
(original)
+++
jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/OperationStatsCollector.java
Mon Jun 25 10:42:16 2018
@@ -32,6 +32,15 @@ public interface OperationStatsCollector
@Override public void finishFailure() {
}
+ @Override public void updateNumDeleted(long num) {
+ }
+
+ @Override public void updateNumCandidates(long num) {
+ }
+
+ @Override public void updateTotalSizeDeleted(long size) {
+ }
+
@Override public void updateDuration(long time, TimeUnit timeUnit) {
}
@@ -53,6 +62,24 @@ public interface OperationStatsCollector
void finishFailure();
/**
+ * Update the number deleted
+ * @param num
+ */
+ void updateNumDeleted(long num);
+
+ /**
+ * Update the number of candidates found
+ * @param num
+ */
+ void updateNumCandidates(long num);
+
+ /**
+ * Update the size deleted
+ * @param size
+ */
+ void updateTotalSizeDeleted(long size);
+
+ /**
* Increment the duration timer
*
* @param time time recorded for the operation
Modified:
jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/BlobGCTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/BlobGCTest.java?rev=1834299&r1=1834298&r2=1834299&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/BlobGCTest.java
(original)
+++
jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/BlobGCTest.java
Mon Jun 25 10:42:16 2018
@@ -34,6 +34,7 @@ import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicReference;
@@ -51,6 +52,7 @@ import org.apache.jackrabbit.core.data.D
import org.apache.jackrabbit.core.data.DataRecord;
import org.apache.jackrabbit.core.data.DataStoreException;
import org.apache.jackrabbit.oak.api.Blob;
+import org.apache.jackrabbit.oak.commons.concurrent.ExecutorCloser;
import org.apache.jackrabbit.oak.commons.junit.LogCustomizer;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.jmx.CheckpointMBean;
@@ -70,6 +72,7 @@ import org.apache.jackrabbit.oak.spi.whi
import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
import org.apache.jackrabbit.oak.stats.Clock;
import org.apache.jackrabbit.oak.stats.DefaultStatisticsProvider;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -78,7 +81,19 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.apache.commons.codec.binary.Hex.encodeHexString;
+import static
org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats
+ .FINISH_FAILURE;
+import static
org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.NAME;
+import static
org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats
+ .NUM_BLOBS_DELETED;
+import static
org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats
+ .NUM_CANDIDATES;
+import static
org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.START;
+import static
org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats
+ .TOTAL_SIZE_DELETED;
+import static org.apache.jackrabbit.oak.plugins.blob.OperationsStatsMBean.TYPE;
import static
org.apache.jackrabbit.oak.plugins.blob.datastore.SharedDataStoreUtils.SharedStoreRecordType.REPOSITORY;
+import static org.apache.jackrabbit.oak.stats.StatsOptions.METRICS_ONLY;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -98,7 +113,9 @@ public class BlobGCTest {
protected BlobReferenceRetriever referenceRetriever;
protected CheckpointMBean checkpointMBean;
-
+ protected ScheduledExecutorService scheduledExecutor;
+ protected ThreadPoolExecutor executor;
+ protected DefaultStatisticsProvider statsProvider;
protected Clock clock;
@Before
@@ -117,6 +134,15 @@ public class BlobGCTest {
};
referenceRetriever = ((MemoryBlobStoreNodeStore)
nodeStore).getBlobReferenceRetriever();
startReferenceTime = ((TimeLapsedBlobStore) blobStore).startTime;
+ scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
+ executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
+ statsProvider = new DefaultStatisticsProvider(scheduledExecutor);
+ }
+
+ @After
+ public void after() {
+ new ExecutorCloser(scheduledExecutor).close();
+ new ExecutorCloser(executor).close();
}
protected Clock getClock() {
@@ -134,6 +160,8 @@ public class BlobGCTest {
Set<String> existingAfterGC = gcInternal(0);
assertTrue(Sets.symmetricDifference(state.blobsPresent,
existingAfterGC).isEmpty());
+ assertStats(1, 0, state.blobsAdded.size() - state.blobsPresent.size(),
+ state.blobsAdded.size() - state.blobsPresent.size());
}
@Test
@@ -149,6 +177,7 @@ public class BlobGCTest {
Set<String> existingAfterGC = gcInternal(afterSetupTime -
startReferenceTime + 2);
assertTrue(Sets.symmetricDifference(state.blobsAdded,
existingAfterGC).isEmpty());
+ assertStats(1, 0, 0, state.blobsAdded.size() -
state.blobsPresent.size());
}
@Test
@@ -173,6 +202,9 @@ public class BlobGCTest {
assertEquals(1, customLogs.getLogs().size());
long deletedSize = (state.blobsAdded.size() -
state.blobsPresent.size()) * 100;
assertTrue(customLogs.getLogs().get(0).contains(String.valueOf(deletedSize)));
+ assertStats(1, 0, state.blobsAdded.size() - state.blobsPresent.size(),
+ state.blobsAdded.size() - state.blobsPresent.size());
+ assertEquals(deletedSize, getStatCount(TOTAL_SIZE_DELETED));
customLogs.finished();
assertTrue(Sets.symmetricDifference(state.blobsPresent,
existingAfterGC).isEmpty());
@@ -189,6 +221,7 @@ public class BlobGCTest {
Set<String> existingAfterGC = gcInternal(0, true);
assertTrue(Sets.symmetricDifference(state.blobsAdded,
existingAfterGC).isEmpty());
+ assertStats(1, 0, 0, 0);
}
protected Set<String> gcInternal(long maxBlobGcInSecs) throws Exception {
@@ -196,21 +229,26 @@ public class BlobGCTest {
}
protected Set<String> gcInternal(long maxBlobGcInSecs, boolean markOnly)
throws Exception {
- ThreadPoolExecutor executor = (ThreadPoolExecutor)
Executors.newFixedThreadPool(10);
MarkSweepGarbageCollector gc = initGC(maxBlobGcInSecs, executor);
gc.collectGarbage(markOnly);
assertEquals(0, executor.getTaskCount());
Set<String> existingAfterGC = iterate();
log.info("{} blobs existing after gc : {}", existingAfterGC.size(),
existingAfterGC);
- assertStats(gc.getOperationStats());
return existingAfterGC;
}
- private void assertStats(OperationsStatsMBean operationStats) {
- assertEquals("Start counter mismatch", 1,
operationStats.getStartCount());
- assertEquals("Finish error mismatch", 0,
operationStats.getFailureCount());
+ private void assertStats(int start, int failure, long deleted, long
candidates) {
+ assertEquals("Start counter mismatch", start, getStatCount(START));
+ assertEquals("Finish error mismatch", failure,
getStatCount(FINISH_FAILURE));
+ assertEquals("Num deleted mismatch", deleted,
getStatCount(NUM_BLOBS_DELETED));
+ assertEquals("Num candidates mismatch", candidates,
getStatCount(NUM_CANDIDATES));
+ }
+
+ private long getStatCount(String name) {
+ return statsProvider.getCounterStats(
+ TYPE + "." + NAME + "." + name, METRICS_ONLY).getCount();
}
private MarkSweepGarbageCollector initGC(long blobGcMaxAgeInSecs,
ThreadPoolExecutor executor)
@@ -220,7 +258,6 @@ public class BlobGCTest {
private MarkSweepGarbageCollector initGC(long blobGcMaxAgeInSecs,
ThreadPoolExecutor executor,
String root) throws Exception {
- DefaultStatisticsProvider statsProvider = new
DefaultStatisticsProvider(Executors.newSingleThreadScheduledExecutor());
String repoId = null;
if (SharedDataStoreUtils.isShared(blobStore)) {
repoId = ClusterRepositoryInfo.getOrCreateId(nodeStore);