summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit
diff options
context:
space:
mode:
authorLaura Hamelin <haowl@google.com>2024-10-16 15:16:00 -0700
committerIvan Frade <ifrade@google.com>2024-10-21 19:05:32 +0000
commitfe8919d107cbfbc52b84f9b8e9fe55668dfbebb1 (patch)
treece3c6beae92db089d6127518fb2a7ec88120835b /org.eclipse.jgit
parent7fed42f860d2af49365283e6fba9a3a2dba9ea53 (diff)
downloadjgit-fe8919d107cbfbc52b84f9b8e9fe55668dfbebb1.tar.gz
jgit-fe8919d107cbfbc52b84f9b8e9fe55668dfbebb1.zip
DfsBlockCache: refactor stats implementations.
The stats interface has an implementation in the interface itself and another inside the PackExtBlockCache class. This asymmetry gets on the way to implement stats-per-table later. Make DfsBlockCacheStats (the stats of a single table) a top-level class and create an aggregator class to combine multiple stats. This makes the stats classes mirror the table classes structure (singles tables + composite). This change is part of a refactor to support providing detailed stats breakdowns for cache implementations using multiple table instances while keeping the existing "aggregated" view of cache stats. Change-Id: I79c11e4ea24afe4b449efdbb47bc81eed363ffd3
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/AggregatedBlockCacheStats.java127
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheStats.java197
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheTable.java194
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/PackExtBlockCacheTable.java100
4 files changed, 332 insertions, 286 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/AggregatedBlockCacheStats.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/AggregatedBlockCacheStats.java
new file mode 100644
index 0000000000..743f4606c4
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/AggregatedBlockCacheStats.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2024, Google LLC and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static org.eclipse.jgit.internal.storage.dfs.DfsBlockCacheTable.BlockCacheStats;
+
+import java.util.List;
+
+import org.eclipse.jgit.internal.storage.pack.PackExt;
+
+/**
+ * Aggregates values for all given {@link BlockCacheStats}.
+ */
+class AggregatedBlockCacheStats implements BlockCacheStats {
+ private final String name;
+
+ private final List<BlockCacheStats> blockCacheStats;
+
+ static BlockCacheStats fromStatsList(String name,
+ List<BlockCacheStats> blockCacheStats) {
+ if (blockCacheStats.size() == 1) {
+ return blockCacheStats.get(0);
+ }
+ return new AggregatedBlockCacheStats(name, blockCacheStats);
+ }
+
+ private AggregatedBlockCacheStats(String name,
+ List<BlockCacheStats> blockCacheStats) {
+ this.name = name;
+ this.blockCacheStats = blockCacheStats;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public long[] getCurrentSize() {
+ long[] sums = emptyPackStats();
+ for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
+ sums = add(sums, blockCacheStatsEntry.getCurrentSize());
+ }
+ return sums;
+ }
+
+ @Override
+ public long[] getHitCount() {
+ long[] sums = emptyPackStats();
+ for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
+ sums = add(sums, blockCacheStatsEntry.getHitCount());
+ }
+ return sums;
+ }
+
+ @Override
+ public long[] getMissCount() {
+ long[] sums = emptyPackStats();
+ for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
+ sums = add(sums, blockCacheStatsEntry.getMissCount());
+ }
+ return sums;
+ }
+
+ @Override
+ public long[] getTotalRequestCount() {
+ long[] sums = emptyPackStats();
+ for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
+ sums = add(sums, blockCacheStatsEntry.getTotalRequestCount());
+ }
+ return sums;
+ }
+
+ @Override
+ public long[] getHitRatio() {
+ long[] hit = getHitCount();
+ long[] miss = getMissCount();
+ long[] ratio = new long[Math.max(hit.length, miss.length)];
+ for (int i = 0; i < ratio.length; i++) {
+ if (i >= hit.length) {
+ ratio[i] = 0;
+ } else if (i >= miss.length) {
+ ratio[i] = 100;
+ } else {
+ long total = hit[i] + miss[i];
+ ratio[i] = total == 0 ? 0 : hit[i] * 100 / total;
+ }
+ }
+ return ratio;
+ }
+
+ @Override
+ public long[] getEvictions() {
+ long[] sums = emptyPackStats();
+ for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
+ sums = add(sums, blockCacheStatsEntry.getEvictions());
+ }
+ return sums;
+ }
+
+ private static long[] emptyPackStats() {
+ return new long[PackExt.values().length];
+ }
+
+ private static long[] add(long[] first, long[] second) {
+ long[] sums = new long[Integer.max(first.length, second.length)];
+ int i;
+ for (i = 0; i < Integer.min(first.length, second.length); i++) {
+ sums[i] = first[i] + second[i];
+ }
+ for (int j = i; j < first.length; j++) {
+ sums[j] = first[i];
+ }
+ for (int j = i; j < second.length; j++) {
+ sums[j] = second[i];
+ }
+ return sums;
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheStats.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheStats.java
new file mode 100644
index 0000000000..518db8c82d
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheStats.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2024, Google LLC and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static org.eclipse.jgit.internal.storage.dfs.DfsBlockCacheTable.BlockCacheStats;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.eclipse.jgit.internal.storage.pack.PackExt;
+
+/**
+ * Keeps track of stats for a Block Cache table.
+ */
+class DfsBlockCacheStats implements BlockCacheStats {
+ private final String name;
+
+ /**
+ * Number of times a block was found in the cache, per pack file extension.
+ */
+ private final AtomicReference<AtomicLong[]> statHit;
+
+ /**
+ * Number of times a block was not found, and had to be loaded, per pack
+ * file extension.
+ */
+ private final AtomicReference<AtomicLong[]> statMiss;
+
+ /**
+ * Number of blocks evicted due to cache being full, per pack file
+ * extension.
+ */
+ private final AtomicReference<AtomicLong[]> statEvict;
+
+ /**
+ * Number of bytes currently loaded in the cache, per pack file extension.
+ */
+ private final AtomicReference<AtomicLong[]> liveBytes;
+
+ DfsBlockCacheStats() {
+ this("");
+ }
+
+ DfsBlockCacheStats(String name) {
+ this.name = name;
+ statHit = new AtomicReference<>(newCounters());
+ statMiss = new AtomicReference<>(newCounters());
+ statEvict = new AtomicReference<>(newCounters());
+ liveBytes = new AtomicReference<>(newCounters());
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Increment the {@code statHit} count.
+ *
+ * @param key
+ * key identifying which liveBytes entry to update.
+ */
+ void incrementHit(DfsStreamKey key) {
+ getStat(statHit, key).incrementAndGet();
+ }
+
+ /**
+ * Increment the {@code statMiss} count.
+ *
+ * @param key
+ * key identifying which liveBytes entry to update.
+ */
+ void incrementMiss(DfsStreamKey key) {
+ getStat(statMiss, key).incrementAndGet();
+ }
+
+ /**
+ * Increment the {@code statEvict} count.
+ *
+ * @param key
+ * key identifying which liveBytes entry to update.
+ */
+ void incrementEvict(DfsStreamKey key) {
+ getStat(statEvict, key).incrementAndGet();
+ }
+
+ /**
+ * Add {@code size} to the {@code liveBytes} count.
+ *
+ * @param key
+ * key identifying which liveBytes entry to update.
+ * @param size
+ * amount to increment the count by.
+ */
+ void addToLiveBytes(DfsStreamKey key, long size) {
+ getStat(liveBytes, key).addAndGet(size);
+ }
+
+ @Override
+ public long[] getCurrentSize() {
+ return getStatVals(liveBytes);
+ }
+
+ @Override
+ public long[] getHitCount() {
+ return getStatVals(statHit);
+ }
+
+ @Override
+ public long[] getMissCount() {
+ return getStatVals(statMiss);
+ }
+
+ @Override
+ public long[] getTotalRequestCount() {
+ AtomicLong[] hit = statHit.get();
+ AtomicLong[] miss = statMiss.get();
+ long[] cnt = new long[Math.max(hit.length, miss.length)];
+ for (int i = 0; i < hit.length; i++) {
+ cnt[i] += hit[i].get();
+ }
+ for (int i = 0; i < miss.length; i++) {
+ cnt[i] += miss[i].get();
+ }
+ return cnt;
+ }
+
+ @Override
+ public long[] getHitRatio() {
+ AtomicLong[] hit = statHit.get();
+ AtomicLong[] miss = statMiss.get();
+ long[] ratio = new long[Math.max(hit.length, miss.length)];
+ for (int i = 0; i < ratio.length; i++) {
+ if (i >= hit.length) {
+ ratio[i] = 0;
+ } else if (i >= miss.length) {
+ ratio[i] = 100;
+ } else {
+ long hitVal = hit[i].get();
+ long missVal = miss[i].get();
+ long total = hitVal + missVal;
+ ratio[i] = total == 0 ? 0 : hitVal * 100 / total;
+ }
+ }
+ return ratio;
+ }
+
+ @Override
+ public long[] getEvictions() {
+ return getStatVals(statEvict);
+ }
+
+ private static AtomicLong[] newCounters() {
+ AtomicLong[] ret = new AtomicLong[PackExt.values().length];
+ for (int i = 0; i < ret.length; i++) {
+ ret[i] = new AtomicLong();
+ }
+ return ret;
+ }
+
+ private static long[] getStatVals(AtomicReference<AtomicLong[]> stat) {
+ AtomicLong[] stats = stat.get();
+ long[] cnt = new long[stats.length];
+ for (int i = 0; i < stats.length; i++) {
+ cnt[i] = stats[i].get();
+ }
+ return cnt;
+ }
+
+ private static AtomicLong getStat(AtomicReference<AtomicLong[]> stats,
+ DfsStreamKey key) {
+ int pos = key.packExtPos;
+ while (true) {
+ AtomicLong[] vals = stats.get();
+ if (pos < vals.length) {
+ return vals[pos];
+ }
+ AtomicLong[] expect = vals;
+ vals = new AtomicLong[Math.max(pos + 1, PackExt.values().length)];
+ System.arraycopy(expect, 0, vals, 0, expect.length);
+ for (int i = expect.length; i < vals.length; i++) {
+ vals[i] = new AtomicLong();
+ }
+ if (stats.compareAndSet(expect, vals)) {
+ return vals[pos];
+ }
+ }
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheTable.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheTable.java
index de5dc23963..43ba8c36ab 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheTable.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheTable.java
@@ -11,10 +11,6 @@
package org.eclipse.jgit.internal.storage.dfs;
import java.io.IOException;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.eclipse.jgit.internal.storage.pack.PackExt;
/**
* Block cache table.
@@ -148,6 +144,12 @@ public interface DfsBlockCacheTable {
* Provides methods used with Block Cache statistics.
*/
interface BlockCacheStats {
+
+ /**
+ * Get the name of the block cache generating this instance.
+ *
+ * @return this cache's name.
+ */
String getName();
/**
@@ -199,186 +201,4 @@ public interface DfsBlockCacheTable {
*/
long[] getEvictions();
}
-
- /**
- * Keeps track of stats for a Block Cache table.
- */
- class DfsBlockCacheStats implements BlockCacheStats {
- private final String name;
-
- /**
- * Number of times a block was found in the cache, per pack file
- * extension.
- */
- private final AtomicReference<AtomicLong[]> statHit;
-
- /**
- * Number of times a block was not found, and had to be loaded, per pack
- * file extension.
- */
- private final AtomicReference<AtomicLong[]> statMiss;
-
- /**
- * Number of blocks evicted due to cache being full, per pack file
- * extension.
- */
- private final AtomicReference<AtomicLong[]> statEvict;
-
- /**
- * Number of bytes currently loaded in the cache, per pack file
- * extension.
- */
- private final AtomicReference<AtomicLong[]> liveBytes;
-
- DfsBlockCacheStats() {
- this("");
- }
-
- DfsBlockCacheStats(String name) {
- this.name = name;
- statHit = new AtomicReference<>(newCounters());
- statMiss = new AtomicReference<>(newCounters());
- statEvict = new AtomicReference<>(newCounters());
- liveBytes = new AtomicReference<>(newCounters());
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- /**
- * Increment the {@code statHit} count.
- *
- * @param key
- * key identifying which liveBytes entry to update.
- */
- void incrementHit(DfsStreamKey key) {
- getStat(statHit, key).incrementAndGet();
- }
-
- /**
- * Increment the {@code statMiss} count.
- *
- * @param key
- * key identifying which liveBytes entry to update.
- */
- void incrementMiss(DfsStreamKey key) {
- getStat(statMiss, key).incrementAndGet();
- }
-
- /**
- * Increment the {@code statEvict} count.
- *
- * @param key
- * key identifying which liveBytes entry to update.
- */
- void incrementEvict(DfsStreamKey key) {
- getStat(statEvict, key).incrementAndGet();
- }
-
- /**
- * Add {@code size} to the {@code liveBytes} count.
- *
- * @param key
- * key identifying which liveBytes entry to update.
- * @param size
- * amount to increment the count by.
- */
- void addToLiveBytes(DfsStreamKey key, long size) {
- getStat(liveBytes, key).addAndGet(size);
- }
-
- @Override
- public long[] getCurrentSize() {
- return getStatVals(liveBytes);
- }
-
- @Override
- public long[] getHitCount() {
- return getStatVals(statHit);
- }
-
- @Override
- public long[] getMissCount() {
- return getStatVals(statMiss);
- }
-
- @Override
- public long[] getTotalRequestCount() {
- AtomicLong[] hit = statHit.get();
- AtomicLong[] miss = statMiss.get();
- long[] cnt = new long[Math.max(hit.length, miss.length)];
- for (int i = 0; i < hit.length; i++) {
- cnt[i] += hit[i].get();
- }
- for (int i = 0; i < miss.length; i++) {
- cnt[i] += miss[i].get();
- }
- return cnt;
- }
-
- @Override
- public long[] getHitRatio() {
- AtomicLong[] hit = statHit.get();
- AtomicLong[] miss = statMiss.get();
- long[] ratio = new long[Math.max(hit.length, miss.length)];
- for (int i = 0; i < ratio.length; i++) {
- if (i >= hit.length) {
- ratio[i] = 0;
- } else if (i >= miss.length) {
- ratio[i] = 100;
- } else {
- long hitVal = hit[i].get();
- long missVal = miss[i].get();
- long total = hitVal + missVal;
- ratio[i] = total == 0 ? 0 : hitVal * 100 / total;
- }
- }
- return ratio;
- }
-
- @Override
- public long[] getEvictions() {
- return getStatVals(statEvict);
- }
-
- private static AtomicLong[] newCounters() {
- AtomicLong[] ret = new AtomicLong[PackExt.values().length];
- for (int i = 0; i < ret.length; i++) {
- ret[i] = new AtomicLong();
- }
- return ret;
- }
-
- private static long[] getStatVals(AtomicReference<AtomicLong[]> stat) {
- AtomicLong[] stats = stat.get();
- long[] cnt = new long[stats.length];
- for (int i = 0; i < stats.length; i++) {
- cnt[i] = stats[i].get();
- }
- return cnt;
- }
-
- private static AtomicLong getStat(AtomicReference<AtomicLong[]> stats,
- DfsStreamKey key) {
- int pos = key.packExtPos;
- while (true) {
- AtomicLong[] vals = stats.get();
- if (pos < vals.length) {
- return vals[pos];
- }
- AtomicLong[] expect = vals;
- vals = new AtomicLong[Math.max(pos + 1,
- PackExt.values().length)];
- System.arraycopy(expect, 0, vals, 0, expect.length);
- for (int i = expect.length; i < vals.length; i++) {
- vals[i] = new AtomicLong();
- }
- if (stats.compareAndSet(expect, vals)) {
- return vals[pos];
- }
- }
- }
- }
-} \ No newline at end of file
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/PackExtBlockCacheTable.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/PackExtBlockCacheTable.java
index 7f21b3f10a..e45643be84 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/PackExtBlockCacheTable.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/PackExtBlockCacheTable.java
@@ -189,7 +189,7 @@ class PackExtBlockCacheTable implements DfsBlockCacheTable {
@Override
public BlockCacheStats getBlockCacheStats() {
- return new CacheStats(name,
+ return AggregatedBlockCacheStats.fromStatsList(name,
blockCacheTableList.stream()
.map(DfsBlockCacheTable::getBlockCacheStats)
.collect(Collectors.toList()));
@@ -213,102 +213,4 @@ class PackExtBlockCacheTable implements DfsBlockCacheTable {
private static PackExt getPackExt(DfsStreamKey key) {
return PackExt.values()[key.packExtPos];
}
-
- private static class CacheStats implements BlockCacheStats {
- private final String name;
-
- private final List<BlockCacheStats> blockCacheStats;
-
- private CacheStats(String name, List<BlockCacheStats> blockCacheStats) {
- this.name = name;
- this.blockCacheStats = blockCacheStats;
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public long[] getCurrentSize() {
- long[] sums = emptyPackStats();
- for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
- sums = add(sums, blockCacheStatsEntry.getCurrentSize());
- }
- return sums;
- }
-
- @Override
- public long[] getHitCount() {
- long[] sums = emptyPackStats();
- for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
- sums = add(sums, blockCacheStatsEntry.getHitCount());
- }
- return sums;
- }
-
- @Override
- public long[] getMissCount() {
- long[] sums = emptyPackStats();
- for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
- sums = add(sums, blockCacheStatsEntry.getMissCount());
- }
- return sums;
- }
-
- @Override
- public long[] getTotalRequestCount() {
- long[] sums = emptyPackStats();
- for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
- sums = add(sums, blockCacheStatsEntry.getTotalRequestCount());
- }
- return sums;
- }
-
- @Override
- public long[] getHitRatio() {
- long[] hit = getHitCount();
- long[] miss = getMissCount();
- long[] ratio = new long[Math.max(hit.length, miss.length)];
- for (int i = 0; i < ratio.length; i++) {
- if (i >= hit.length) {
- ratio[i] = 0;
- } else if (i >= miss.length) {
- ratio[i] = 100;
- } else {
- long total = hit[i] + miss[i];
- ratio[i] = total == 0 ? 0 : hit[i] * 100 / total;
- }
- }
- return ratio;
- }
-
- @Override
- public long[] getEvictions() {
- long[] sums = emptyPackStats();
- for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
- sums = add(sums, blockCacheStatsEntry.getEvictions());
- }
- return sums;
- }
-
- private static long[] emptyPackStats() {
- return new long[PackExt.values().length];
- }
-
- private static long[] add(long[] first, long[] second) {
- long[] sums = new long[Integer.max(first.length, second.length)];
- int i;
- for (i = 0; i < Integer.min(first.length, second.length); i++) {
- sums[i] = first[i] + second[i];
- }
- for (int j = i; j < first.length; j++) {
- sums[j] = first[i];
- }
- for (int j = i; j < second.length; j++) {
- sums[j] = second[i];
- }
- return sums;
- }
- }
}