Skip to content

Commit c96f474

Browse files
author
Peter Alfonsi
committed
Removed serialization logic of MDCS from this PR
Signed-off-by: Peter Alfonsi <[email protected]>
1 parent c0c7b8e commit c96f474

File tree

4 files changed

+76
-143
lines changed

4 files changed

+76
-143
lines changed

server/src/main/java/org/opensearch/common/cache/stats/CacheStats.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
package org.opensearch.common.cache.stats;
1010

1111
import org.opensearch.common.annotation.ExperimentalApi;
12-
import org.opensearch.core.common.io.stream.Writeable;
1312

1413
/**
1514
* Interface for access to any cache stats. Allows accessing stats by dimension values.
@@ -18,7 +17,7 @@
1817
* @opensearch.experimental
1918
*/
2019
@ExperimentalApi
21-
public interface CacheStats extends Writeable {// TODO: also extends ToXContentFragment (in API PR)
20+
public interface CacheStats { // TODO: also extends Writeable, ToXContentFragment (in API PR)
2221

2322
// Method to get all 5 values at once
2423
CacheStatsCounterSnapshot getTotalStats();

server/src/main/java/org/opensearch/common/cache/stats/MultiDimensionCacheStats.java

Lines changed: 0 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@
88

99
package org.opensearch.common.cache.stats;
1010

11-
import org.opensearch.core.common.io.stream.StreamInput;
12-
import org.opensearch.core.common.io.stream.StreamOutput;
13-
14-
import java.io.IOException;
15-
import java.util.ArrayList;
1611
import java.util.HashMap;
1712
import java.util.List;
1813
import java.util.Map;
@@ -35,72 +30,6 @@ public MultiDimensionCacheStats(MDCSDimensionNode statsRoot, List<String> dimens
3530
this.dimensionNames = dimensionNames;
3631
}
3732

38-
public MultiDimensionCacheStats(StreamInput in) throws IOException {
39-
// Because we write in preorder order, the parent of the next node we read will always be one of the ancestors
40-
// of the last node we read. This allows us to avoid ambiguity if nodes have the same dimension value, without
41-
// having to serialize the whole path to each node.
42-
this.dimensionNames = List.of(in.readStringArray());
43-
this.statsRoot = new MDCSDimensionNode("", true);
44-
readAndAttachDimensionNodeRecursive(in, List.of(statsRoot));
45-
// Finally, update sum-of-children stats for the root node
46-
CacheStatsCounter totalStats = new CacheStatsCounter();
47-
for (MDCSDimensionNode child : statsRoot.children.values()) {
48-
totalStats.add(child.getStats());
49-
}
50-
statsRoot.setStats(totalStats.snapshot());
51-
}
52-
53-
@Override
54-
public void writeTo(StreamOutput out) throws IOException {
55-
// Write each node in preorder order, along with its depth.
56-
// Then, when rebuilding the tree from the stream, we can always find the correct parent to attach each node to.
57-
out.writeStringArray(dimensionNames.toArray(new String[0]));
58-
for (MDCSDimensionNode child : statsRoot.children.values()) {
59-
writeDimensionNodeRecursive(out, child, 1);
60-
}
61-
out.writeBoolean(false); // Write false to signal there are no more nodes
62-
}
63-
64-
private void writeDimensionNodeRecursive(StreamOutput out, MDCSDimensionNode node, int depth) throws IOException {
65-
out.writeBoolean(true); // Signals there is a following node to deserialize
66-
out.writeVInt(depth);
67-
out.writeString(node.getDimensionValue());
68-
node.getStats().writeTo(out);
69-
70-
if (!node.children.isEmpty()) {
71-
// Not a leaf node
72-
out.writeBoolean(true); // Write true to indicate we should re-create a map on deserialization
73-
for (MDCSDimensionNode child : node.children.values()) {
74-
writeDimensionNodeRecursive(out, child, depth + 1);
75-
}
76-
} else {
77-
out.writeBoolean(false); // Write false to indicate we should not re-create a map on deserialization
78-
}
79-
}
80-
81-
/**
82-
* Reads a serialized dimension node, attaches it to its appropriate place in the tree, and returns the list of
83-
* ancestors of the newly attached node.
84-
*/
85-
private void readAndAttachDimensionNodeRecursive(StreamInput in, List<MDCSDimensionNode> ancestorsOfLastRead) // List<MDCSDimensionNode>
86-
throws IOException {
87-
boolean hasNextNode = in.readBoolean();
88-
if (hasNextNode) {
89-
int depth = in.readVInt();
90-
String nodeDimensionValue = in.readString();
91-
CacheStatsCounterSnapshot stats = new CacheStatsCounterSnapshot(in);
92-
boolean doRecreateMap = in.readBoolean();
93-
94-
MDCSDimensionNode result = new MDCSDimensionNode(nodeDimensionValue, doRecreateMap, stats);
95-
MDCSDimensionNode parent = ancestorsOfLastRead.get(depth - 1);
96-
parent.getChildren().put(nodeDimensionValue, result);
97-
List<MDCSDimensionNode> ancestors = new ArrayList<>(ancestorsOfLastRead.subList(0, depth));
98-
ancestors.add(result);
99-
readAndAttachDimensionNodeRecursive(in, ancestors);
100-
}
101-
// If !hasNextNode, there are no more nodes, so we are done
102-
}
103-
10433
@Override
10534
public CacheStatsCounterSnapshot getTotalStats() {
10635
return statsRoot.getStats();

server/src/test/java/org/opensearch/common/cache/stats/MultiDimensionCacheStatsTests.java

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,46 @@
88

99
package org.opensearch.common.cache.stats;
1010

11-
import org.opensearch.common.io.stream.BytesStreamOutput;
12-
import org.opensearch.core.common.bytes.BytesReference;
13-
import org.opensearch.core.common.io.stream.BytesStreamInput;
1411
import org.opensearch.test.OpenSearchTestCase;
1512

16-
import java.util.ArrayList;
1713
import java.util.List;
1814
import java.util.Map;
1915

2016
public class MultiDimensionCacheStatsTests extends OpenSearchTestCase {
21-
public void testSerialization() throws Exception {
22-
List<String> dimensionNames = List.of("dim1", "dim2", "dim3");
17+
18+
public void testGet() throws Exception {
19+
List<String> dimensionNames = List.of("dim1", "dim2", "dim3", "dim4");
2320
StatsHolder statsHolder = new StatsHolder(dimensionNames);
2421
Map<String, List<String>> usedDimensionValues = StatsHolderTests.getUsedDimensionValues(statsHolder, 10);
25-
StatsHolderTests.populateStats(statsHolder, usedDimensionValues, 100, 10);
22+
Map<List<String>, CacheStatsCounter> expected = StatsHolderTests.populateStats(statsHolder, usedDimensionValues, 1000, 10);
2623
MultiDimensionCacheStats stats = (MultiDimensionCacheStats) statsHolder.getCacheStats();
2724

28-
BytesStreamOutput os = new BytesStreamOutput();
29-
stats.writeTo(os);
30-
BytesStreamInput is = new BytesStreamInput(BytesReference.toBytes(os.bytes()));
31-
MultiDimensionCacheStats deserialized = new MultiDimensionCacheStats(is);
25+
// test the value in the map is as expected for each distinct combination of values
26+
for (List<String> dimensionValues : expected.keySet()) {
27+
CacheStatsCounter expectedCounter = expected.get(dimensionValues);
28+
29+
CacheStatsCounterSnapshot actualStatsHolder = StatsHolderTests.getNode(dimensionValues, statsHolder.getStatsRoot())
30+
.getStatsSnapshot();
31+
CacheStatsCounterSnapshot actualCacheStats = getNode(dimensionValues, stats.getStatsRoot()).getStats();
32+
33+
assertEquals(expectedCounter.snapshot(), actualStatsHolder);
34+
assertEquals(expectedCounter.snapshot(), actualCacheStats);
35+
}
3236

33-
assertEquals(stats.dimensionNames, deserialized.dimensionNames);
34-
List<List<String>> pathsInOriginal = new ArrayList<>();
35-
getAllPathsInTree(stats.getStatsRoot(), new ArrayList<>(), pathsInOriginal);
36-
for (List<String> path : pathsInOriginal) {
37-
MultiDimensionCacheStats.MDCSDimensionNode originalNode = getNode(path, stats.statsRoot);
38-
MultiDimensionCacheStats.MDCSDimensionNode deserializedNode = getNode(path, deserialized.statsRoot);
39-
assertNotNull(deserializedNode);
40-
assertEquals(originalNode.getDimensionValue(), deserializedNode.getDimensionValue());
41-
assertEquals(originalNode.getStats(), deserializedNode.getStats());
37+
// test gets for total (this also checks sum-of-children logic)
38+
CacheStatsCounter expectedTotal = new CacheStatsCounter();
39+
for (List<String> dims : expected.keySet()) {
40+
expectedTotal.add(expected.get(dims));
4241
}
42+
assertEquals(expectedTotal.snapshot(), stats.getTotalStats());
43+
44+
assertEquals(expectedTotal.getHits(), stats.getTotalHits());
45+
assertEquals(expectedTotal.getMisses(), stats.getTotalMisses());
46+
assertEquals(expectedTotal.getEvictions(), stats.getTotalEvictions());
47+
assertEquals(expectedTotal.getSizeInBytes(), stats.getTotalSizeInBytes());
48+
assertEquals(expectedTotal.getEntries(), stats.getTotalEntries());
49+
50+
assertSumOfChildrenStats(stats.getStatsRoot());
4351
}
4452

4553
public void testEmptyDimsList() throws Exception {
@@ -54,22 +62,6 @@ public void testEmptyDimsList() throws Exception {
5462
assertEquals(stats.getTotalStats(), statsRoot.getStats());
5563
}
5664

57-
private void getAllPathsInTree(
58-
MultiDimensionCacheStats.MDCSDimensionNode currentNode,
59-
List<String> pathToCurrentNode,
60-
List<List<String>> allPaths
61-
) {
62-
allPaths.add(pathToCurrentNode);
63-
if (currentNode.getChildren() != null && !currentNode.getChildren().isEmpty()) {
64-
// not a leaf node
65-
for (MultiDimensionCacheStats.MDCSDimensionNode child : currentNode.getChildren().values()) {
66-
List<String> pathToChild = new ArrayList<>(pathToCurrentNode);
67-
pathToChild.add(child.getDimensionValue());
68-
getAllPathsInTree(child, pathToChild, allPaths);
69-
}
70-
}
71-
}
72-
7365
private MultiDimensionCacheStats.MDCSDimensionNode getNode(
7466
List<String> dimensionValues,
7567
MultiDimensionCacheStats.MDCSDimensionNode root
@@ -83,4 +75,17 @@ private MultiDimensionCacheStats.MDCSDimensionNode getNode(
8375
}
8476
return current;
8577
}
78+
79+
private void assertSumOfChildrenStats(MultiDimensionCacheStats.MDCSDimensionNode current) {
80+
if (!current.children.isEmpty()) {
81+
CacheStatsCounter expectedTotal = new CacheStatsCounter();
82+
for (MultiDimensionCacheStats.MDCSDimensionNode child : current.children.values()) {
83+
expectedTotal.add(child.getStats());
84+
}
85+
assertEquals(expectedTotal.snapshot(), current.getStats());
86+
for (MultiDimensionCacheStats.MDCSDimensionNode child : current.children.values()) {
87+
assertSumOfChildrenStats(child);
88+
}
89+
}
90+
}
8691
}

server/src/test/java/org/opensearch/common/cache/stats/StatsHolderTests.java

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,6 @@ static Map<List<String>, CacheStatsCounter> populateStats(
187187
int numRepetitionsPerValue
188188
) throws InterruptedException {
189189
Map<List<String>, CacheStatsCounter> expected = new ConcurrentHashMap<>();
190-
191190
Thread[] threads = new Thread[numDistinctValuePairs];
192191
CountDownLatch countDownLatch = new CountDownLatch(numDistinctValuePairs);
193192
Random rand = Randomness.get();
@@ -196,42 +195,23 @@ static Map<List<String>, CacheStatsCounter> populateStats(
196195
dimensionsForThreads.add(getRandomDimList(statsHolder.getDimensionNames(), usedDimensionValues, true, rand));
197196
int finalI = i;
198197
threads[i] = new Thread(() -> {
199-
Random threadRand = Randomness.get(); // TODO: This always has the same seed for each thread, causing only 1 set of values
198+
Random threadRand = Randomness.get();
200199
List<String> dimensions = dimensionsForThreads.get(finalI);
201200
expected.computeIfAbsent(dimensions, (key) -> new CacheStatsCounter());
202-
203201
for (int j = 0; j < numRepetitionsPerValue; j++) {
204-
int numHitIncrements = threadRand.nextInt(10);
205-
for (int k = 0; k < numHitIncrements; k++) {
206-
statsHolder.incrementHits(dimensions);
207-
expected.get(dimensions).hits.inc();
208-
}
209-
int numMissIncrements = threadRand.nextInt(10);
210-
for (int k = 0; k < numMissIncrements; k++) {
211-
statsHolder.incrementMisses(dimensions);
212-
expected.get(dimensions).misses.inc();
213-
}
214-
int numEvictionIncrements = threadRand.nextInt(10);
215-
for (int k = 0; k < numEvictionIncrements; k++) {
216-
statsHolder.incrementEvictions(dimensions);
217-
expected.get(dimensions).evictions.inc();
218-
}
219-
int numMemorySizeIncrements = threadRand.nextInt(10);
220-
for (int k = 0; k < numMemorySizeIncrements; k++) {
221-
long memIncrementAmount = threadRand.nextInt(5000);
222-
statsHolder.incrementSizeInBytes(dimensions, memIncrementAmount);
223-
expected.get(dimensions).sizeInBytes.inc(memIncrementAmount);
224-
}
225-
int numEntryIncrements = threadRand.nextInt(9) + 1;
226-
for (int k = 0; k < numEntryIncrements; k++) {
227-
statsHolder.incrementEntries(dimensions);
228-
expected.get(dimensions).entries.inc();
229-
}
230-
int numEntryDecrements = threadRand.nextInt(numEntryIncrements);
231-
for (int k = 0; k < numEntryDecrements; k++) {
232-
statsHolder.decrementEntries(dimensions);
233-
expected.get(dimensions).entries.dec();
234-
}
202+
CacheStatsCounter statsToInc = new CacheStatsCounter(
203+
threadRand.nextInt(10),
204+
threadRand.nextInt(10),
205+
threadRand.nextInt(10),
206+
threadRand.nextInt(5000),
207+
threadRand.nextInt(10)
208+
);
209+
expected.get(dimensions).hits.inc(statsToInc.getHits());
210+
expected.get(dimensions).misses.inc(statsToInc.getMisses());
211+
expected.get(dimensions).evictions.inc(statsToInc.getEvictions());
212+
expected.get(dimensions).sizeInBytes.inc(statsToInc.getSizeInBytes());
213+
expected.get(dimensions).entries.inc(statsToInc.getEntries());
214+
StatsHolderTests.populateStatsHolderFromStatsValueMap(statsHolder, Map.of(dimensions, statsToInc));
235215
}
236216
countDownLatch.countDown();
237217
});
@@ -284,4 +264,24 @@ private void assertSumOfChildrenStats(DimensionNode current) {
284264
}
285265
}
286266
}
267+
268+
static void populateStatsHolderFromStatsValueMap(StatsHolder statsHolder, Map<List<String>, CacheStatsCounter> statsMap) {
269+
for (Map.Entry<List<String>, CacheStatsCounter> entry : statsMap.entrySet()) {
270+
CacheStatsCounter stats = entry.getValue();
271+
List<String> dims = entry.getKey();
272+
for (int i = 0; i < stats.getHits(); i++) {
273+
statsHolder.incrementHits(dims);
274+
}
275+
for (int i = 0; i < stats.getMisses(); i++) {
276+
statsHolder.incrementMisses(dims);
277+
}
278+
for (int i = 0; i < stats.getEvictions(); i++) {
279+
statsHolder.incrementEvictions(dims);
280+
}
281+
statsHolder.incrementSizeInBytes(dims, stats.getSizeInBytes());
282+
for (int i = 0; i < stats.getEntries(); i++) {
283+
statsHolder.incrementEntries(dims);
284+
}
285+
}
286+
}
287287
}

0 commit comments

Comments
 (0)