blob: 4267e50208f6434783520931212c438691df1088 [file] [log] [blame]
diff --git a/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyReader.java b/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyReader.java
index c72e60b..cde56e1 100644
--- a/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyReader.java
+++ b/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/DirectoryTaxonomyReader.java
@@ -17,6 +17,10 @@
package org.apache.lucene.facet.taxonomy.directory;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -30,12 +34,17 @@ import org.apache.lucene.facet.taxonomy.TaxonomyReader;
import org.apache.lucene.index.CorruptIndexException; // javadocs
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.MultiFields;
import org.apache.lucene.index.PostingsEnum;
+import org.apache.lucene.index.SegmentReader;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.Accountable;
+import org.apache.lucene.util.Accountables;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.IOUtils;
+import org.apache.lucene.util.RamUsageEstimator;
/**
* A {@link TaxonomyReader} which retrieves stored taxonomy information from a
@@ -49,11 +58,14 @@ import org.apache.lucene.util.IOUtils;
*
* @lucene.experimental
*/
-public class DirectoryTaxonomyReader extends TaxonomyReader {
+public class DirectoryTaxonomyReader extends TaxonomyReader implements Accountable {
private static final Logger logger = Logger.getLogger(DirectoryTaxonomyReader.class.getName());
private static final int DEFAULT_CACHE_VALUE = 4000;
+
+ // NOTE: very coarse estimate!
+ private static final int BYTES_PER_CACHE_ENTRY = 4 * RamUsageEstimator.NUM_BYTES_OBJECT_REF + 4 * RamUsageEstimator.NUM_BYTES_OBJECT_HEADER + 8 * RamUsageEstimator.NUM_BYTES_CHAR;
private final DirectoryTaxonomyWriter taxoWriter;
private final long taxoEpoch; // used in doOpenIfChanged
@@ -325,7 +337,51 @@ public class DirectoryTaxonomyReader extends TaxonomyReader {
ensureOpen();
return indexReader.numDocs();
}
+
+ @Override
+ public synchronized long ramBytesUsed() {
+ ensureOpen();
+ long ramBytesUsed = 0;
+ for (LeafReaderContext ctx : indexReader.leaves()) {
+ ramBytesUsed += ((SegmentReader) ctx.reader()).ramBytesUsed();
+ }
+ if (taxoArrays != null) {
+ ramBytesUsed += taxoArrays.ramBytesUsed();
+ }
+ synchronized (categoryCache) {
+ ramBytesUsed += BYTES_PER_CACHE_ENTRY * categoryCache.size();
+ }
+
+ synchronized (ordinalCache) {
+ ramBytesUsed += BYTES_PER_CACHE_ENTRY * ordinalCache.size();
+ }
+
+ return ramBytesUsed;
+ }
+ @Override
+ public synchronized Collection<Accountable> getChildResources() {
+ final List<Accountable> resources = new ArrayList<>();
+ long ramBytesUsed = 0;
+ for (LeafReaderContext ctx : indexReader.leaves()) {
+ ramBytesUsed += ((SegmentReader) ctx.reader()).ramBytesUsed();
+ }
+ resources.add(Accountables.namedAccountable("indexReader", ramBytesUsed));
+ if (taxoArrays != null) {
+ resources.add(Accountables.namedAccountable("taxoArrays", taxoArrays));
+ }
+
+ synchronized (categoryCache) {
+ resources.add(Accountables.namedAccountable("categoryCache", BYTES_PER_CACHE_ENTRY * categoryCache.size()));
+ }
+
+ synchronized (ordinalCache) {
+ resources.add(Accountables.namedAccountable("ordinalCache", BYTES_PER_CACHE_ENTRY * ordinalCache.size()));
+ }
+
+ return Collections.unmodifiableList(resources);
+ }
+
/**
* setCacheSize controls the maximum allowed size of each of the caches
* used by {@link #getPath(int)} and {@link #getOrdinal(FacetLabel)}.
diff --git a/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/TaxonomyIndexArrays.java b/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/TaxonomyIndexArrays.java
index bdd5c80..dc4d18a 100644
--- a/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/TaxonomyIndexArrays.java
+++ b/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/directory/TaxonomyIndexArrays.java
@@ -16,16 +16,23 @@
*/
package org.apache.lucene.facet.taxonomy.directory;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
import org.apache.lucene.facet.taxonomy.ParallelTaxonomyArrays;
import org.apache.lucene.facet.taxonomy.TaxonomyReader;
import org.apache.lucene.index.CorruptIndexException;
-import org.apache.lucene.index.PostingsEnum;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.MultiFields;
+import org.apache.lucene.index.PostingsEnum;
import org.apache.lucene.search.DocIdSetIterator;
+import org.apache.lucene.util.Accountable;
+import org.apache.lucene.util.Accountables;
import org.apache.lucene.util.ArrayUtil;
-
-import java.io.IOException;
+import org.apache.lucene.util.RamUsageEstimator;
/**
* A {@link ParallelTaxonomyArrays} that are initialized from the taxonomy
@@ -33,7 +40,7 @@ import java.io.IOException;
*
* @lucene.experimental
*/
-class TaxonomyIndexArrays extends ParallelTaxonomyArrays {
+class TaxonomyIndexArrays extends ParallelTaxonomyArrays implements Accountable {
private final int[] parents;
@@ -214,4 +221,29 @@ class TaxonomyIndexArrays extends ParallelTaxonomyArrays {
return siblings;
}
+ @Override
+ public synchronized long ramBytesUsed() {
+ long ramBytesUsed = RamUsageEstimator.NUM_BYTES_OBJECT_HEADER + 3 * RamUsageEstimator.NUM_BYTES_OBJECT_REF + RamUsageEstimator.NUM_BYTES_BOOLEAN;
+ ramBytesUsed += RamUsageEstimator.shallowSizeOf(parents);
+ if (children != null) {
+ ramBytesUsed += RamUsageEstimator.shallowSizeOf(children);
+ }
+ if (siblings != null) {
+ ramBytesUsed += RamUsageEstimator.shallowSizeOf(siblings);
+ }
+ return ramBytesUsed;
+ }
+
+ @Override
+ public synchronized Collection<Accountable> getChildResources() {
+ final List<Accountable> resources = new ArrayList<>();
+ resources.add(Accountables.namedAccountable("parents", RamUsageEstimator.shallowSizeOf(parents)));
+ if (children != null) {
+ resources.add(Accountables.namedAccountable("children", RamUsageEstimator.shallowSizeOf(children)));
+ }
+ if (siblings != null) {
+ resources.add(Accountables.namedAccountable("siblings", RamUsageEstimator.shallowSizeOf(siblings)));
+ }
+ return Collections.unmodifiableList(resources);
+ }
}
diff --git a/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyReader.java b/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyReader.java
index 1982048..b47ce0b 100644
--- a/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyReader.java
+++ b/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyReader.java
@@ -25,17 +25,18 @@ import java.util.Set;
import org.apache.lucene.analysis.MockAnalyzer;
import org.apache.lucene.facet.FacetTestCase;
import org.apache.lucene.facet.taxonomy.FacetLabel;
-import org.apache.lucene.facet.taxonomy.TaxonomyReader;
import org.apache.lucene.facet.taxonomy.TaxonomyReader.ChildrenIterator;
+import org.apache.lucene.facet.taxonomy.TaxonomyReader;
import org.apache.lucene.facet.taxonomy.TaxonomyWriter;
import org.apache.lucene.index.IndexWriter;
-import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
+import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.LogByteSizeMergePolicy;
import org.apache.lucene.index.LogMergePolicy;
import org.apache.lucene.store.AlreadyClosedException;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
+import org.apache.lucene.util.Accountables;
import org.apache.lucene.util.IOUtils;
import org.junit.Test;
@@ -529,5 +530,33 @@ public class TestDirectoryTaxonomyReader extends FacetTestCase {
dir.close();
}
-
+
+ public void testAccountable() throws Exception {
+ Directory dir = newDirectory();
+ DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(dir);
+ int numCategories = atLeast(10);
+ int numA = 0, numB = 0;
+ Random random = random();
+ // add the two categories for which we'll also add children (so asserts are simpler)
+ taxoWriter.addCategory(new FacetLabel("a"));
+ taxoWriter.addCategory(new FacetLabel("b"));
+ for (int i = 0; i < numCategories; i++) {
+ if (random.nextBoolean()) {
+ taxoWriter.addCategory(new FacetLabel("a", Integer.toString(i)));
+ ++numA;
+ } else {
+ taxoWriter.addCategory(new FacetLabel("b", Integer.toString(i)));
+ ++numB;
+ }
+ }
+ // add category with no children
+ taxoWriter.addCategory(new FacetLabel("c"));
+ taxoWriter.close();
+
+ DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(dir);
+ assertTrue(taxoReader.ramBytesUsed() > 0);
+ assertTrue(taxoReader.getChildResources().size() > 0);
+ taxoReader.close();
+ dir.close();
+ }
}