diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 8b0b183bb58..516863edc1a 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -114,6 +114,8 @@ Other Changes
* SOLR-7358: TestRestoreCore fails in Windows (Ishan Chattopadhyaya via Varun Thacker)
+* SOLR-7371: Make DocSet implement Accountable to estimate memory usage. (yonik, shalin)
+
================== 5.1.0 ==================
Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release
diff --git a/solr/core/src/java/org/apache/solr/search/BitDocSet.java b/solr/core/src/java/org/apache/solr/search/BitDocSet.java
index bc72e57ac18..dd0b6ffabac 100644
--- a/solr/core/src/java/org/apache/solr/search/BitDocSet.java
+++ b/solr/core/src/java/org/apache/solr/search/BitDocSet.java
@@ -17,16 +17,21 @@
package org.apache.solr.search;
+import java.util.Collection;
+import java.util.Collections;
+
import org.apache.lucene.index.LeafReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.BitsFilteredDocIdSet;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Filter;
+import org.apache.lucene.util.Accountable;
import org.apache.lucene.util.BitDocIdSet;
import org.apache.lucene.util.BitSetIterator;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.FixedBitSet;
+import org.apache.lucene.util.RamUsageEstimator;
/**
* BitDocSet
represents an unordered set of Lucene Document Ids
@@ -35,6 +40,8 @@ import org.apache.lucene.util.FixedBitSet;
* @since solr 0.9
*/
public class BitDocSet extends DocSetBase {
+ private static final long BASE_RAM_BYTES_USED = RamUsageEstimator.shallowSizeOfInstance(BitDocSet.class);
+
final FixedBitSet bits;
int size; // number of docs in the set (cached for perf)
@@ -253,11 +260,6 @@ public class BitDocSet extends DocSetBase {
return new BitDocSet(newbits);
}
- @Override
- public long memSize() {
- return (bits.getBits().length << 3) + 16;
- }
-
@Override
protected BitDocSet clone() {
return new BitDocSet(bits.clone(), size);
@@ -359,4 +361,14 @@ public class BitDocSet extends DocSetBase {
}
};
}
+
+ @Override
+ public long ramBytesUsed() {
+ return BASE_RAM_BYTES_USED + bits.ramBytesUsed();
+ }
+
+ @Override
+ public Collection getChildResources() {
+ return Collections.emptyList();
+ }
}
diff --git a/solr/core/src/java/org/apache/solr/search/DocSet.java b/solr/core/src/java/org/apache/solr/search/DocSet.java
index d918c6dcc3c..de98d07042d 100644
--- a/solr/core/src/java/org/apache/solr/search/DocSet.java
+++ b/solr/core/src/java/org/apache/solr/search/DocSet.java
@@ -20,6 +20,7 @@ package org.apache.solr.search;
import java.io.Closeable;
import org.apache.lucene.search.Filter;
+import org.apache.lucene.util.Accountable;
import org.apache.solr.common.SolrException;
/**
@@ -32,7 +33,7 @@ import org.apache.solr.common.SolrException;
*
* @since solr 0.9
*/
-public interface DocSet extends Closeable /* extends Collection */ {
+public interface DocSet extends Closeable, Accountable /* extends Collection */ {
/**
* Adds the specified document if it is not currently in the DocSet
@@ -77,15 +78,6 @@ public interface DocSet extends Closeable /* extends Collection */ {
*/
public DocIterator iterator();
- /**
- * Returns the approximate amount of memory taken by this DocSet.
- * This is only an approximation and doesn't take into account java object overhead.
- *
- * @return
- * the approximate memory consumption in bytes
- */
- public long memSize();
-
/**
* Returns the intersection of this set with another set. Neither set is modified - a new DocSet is
* created and returned.
diff --git a/solr/core/src/java/org/apache/solr/search/DocSlice.java b/solr/core/src/java/org/apache/solr/search/DocSlice.java
index 00a0ebc0e89..a3500d02866 100644
--- a/solr/core/src/java/org/apache/solr/search/DocSlice.java
+++ b/solr/core/src/java/org/apache/solr/search/DocSlice.java
@@ -18,6 +18,11 @@
package org.apache.solr.search;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.lucene.util.Accountable;
+import org.apache.lucene.util.RamUsageEstimator;
/**
* DocSlice
implements DocList as an array of docids and optional scores.
@@ -26,6 +31,8 @@ import java.util.Arrays;
* @since solr 0.9
*/
public class DocSlice extends DocSetBase implements DocList {
+ private static final long BASE_RAM_BYTES_USED = RamUsageEstimator.shallowSizeOfInstance(DocSlice.class);
+
final int offset; // starting position of the docs (zero based)
final int len; // number of positions used in arrays
final int[] docs; // a slice of documents (docs 0-100 of the query)
@@ -34,6 +41,8 @@ public class DocSlice extends DocSetBase implements DocList {
final int matches;
final float maxScore;
+ final long ramBytesUsed;
+
/**
* Primary constructor for a DocSlice instance.
*
@@ -50,6 +59,7 @@ public class DocSlice extends DocSetBase implements DocList {
this.scores=scores;
this.matches=matches;
this.maxScore=maxScore;
+ this.ramBytesUsed = BASE_RAM_BYTES_USED + RamUsageEstimator.sizeOf(docs) + RamUsageEstimator.sizeOf(scores);
}
@Override
@@ -85,14 +95,6 @@ public class DocSlice extends DocSetBase implements DocList {
public int matches() { return matches; }
- @Override
- public long memSize() {
- return (docs.length<<2)
- + (scores==null ? 0 : (scores.length<<2))
- + 24;
- }
-
-
@Override
public boolean exists(int doc) {
int end = offset+len;
@@ -175,4 +177,14 @@ public class DocSlice extends DocSetBase implements DocList {
} catch (CloneNotSupportedException e) {}
return null;
}
+
+ @Override
+ public long ramBytesUsed() {
+ return ramBytesUsed;
+ }
+
+ @Override
+ public Collection getChildResources() {
+ return Collections.emptyList();
+ }
}
diff --git a/solr/core/src/java/org/apache/solr/search/HashDocSet.java b/solr/core/src/java/org/apache/solr/search/HashDocSet.java
index 28ed05abe01..892bee6eadc 100644
--- a/solr/core/src/java/org/apache/solr/search/HashDocSet.java
+++ b/solr/core/src/java/org/apache/solr/search/HashDocSet.java
@@ -17,7 +17,12 @@
package org.apache.solr.search;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.lucene.util.Accountable;
import org.apache.lucene.util.BitUtil;
+import org.apache.lucene.util.RamUsageEstimator;
/**
@@ -30,6 +35,8 @@ import org.apache.lucene.util.BitUtil;
* @since solr 0.9
*/
public final class HashDocSet extends DocSetBase {
+ private static final long BASE_RAM_BYTES_USED = RamUsageEstimator.shallowSizeOfInstance(HashDocSet.class);
+
/** Default load factor to use for HashDocSets. We keep track of the inverse
* since multiplication is so much faster than division. The default
* is 1.0f / 0.75f
@@ -48,10 +55,13 @@ public final class HashDocSet extends DocSetBase {
private final int mask;
+ private final long ramBytesUsed;
+
public HashDocSet(HashDocSet set) {
this.table = set.table.clone();
this.size = set.size;
this.mask = set.mask;
+ this.ramBytesUsed = BASE_RAM_BYTES_USED + RamUsageEstimator.sizeOf(table);
}
/** Create a HashDocSet from a list of *unique* ids */
@@ -79,6 +89,8 @@ public final class HashDocSet extends DocSetBase {
}
size = len;
+
+ ramBytesUsed = BASE_RAM_BYTES_USED + RamUsageEstimator.sizeOf(table);
}
void put(int doc) {
@@ -155,11 +167,6 @@ public final class HashDocSet extends DocSetBase {
};
}
- @Override
- public long memSize() {
- return (table.length<<2) + 20;
- }
-
@Override
public DocSet intersection(DocSet other) {
if (other instanceof HashDocSet) {
@@ -296,4 +303,15 @@ public final class HashDocSet extends DocSetBase {
// don't implement andNotSize() and unionSize() on purpose... they are implemented
// in BaseDocSet in terms of intersectionSize().
+
+
+ @Override
+ public long ramBytesUsed() {
+ return ramBytesUsed;
+ }
+
+ @Override
+ public Collection getChildResources() {
+ return Collections.emptyList();
+ }
}
diff --git a/solr/core/src/java/org/apache/solr/search/SortedIntDocSet.java b/solr/core/src/java/org/apache/solr/search/SortedIntDocSet.java
index db4bd1c266d..33f58728f87 100644
--- a/solr/core/src/java/org/apache/solr/search/SortedIntDocSet.java
+++ b/solr/core/src/java/org/apache/solr/search/SortedIntDocSet.java
@@ -17,12 +17,16 @@
package org.apache.solr.search;
+import java.util.Collection;
+import java.util.Collections;
+
import org.apache.lucene.index.LeafReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.BitsFilteredDocIdSet;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Filter;
+import org.apache.lucene.util.Accountable;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.FixedBitSet;
import org.apache.lucene.util.RamUsageEstimator;
@@ -31,13 +35,17 @@ import org.apache.lucene.util.RamUsageEstimator;
* SortedIntDocSet
represents a sorted set of Lucene Document Ids.
*/
public class SortedIntDocSet extends DocSetBase {
+ private static final long BASE_RAM_BYTES_USED = RamUsageEstimator.shallowSizeOfInstance(SortedIntDocSet.class);
+
protected final int[] docs;
+ protected final long ramBytesUsed;
/**
* @param docs Sorted list of ids
*/
public SortedIntDocSet(int[] docs) {
this.docs = docs;
+ this.ramBytesUsed = BASE_RAM_BYTES_USED + RamUsageEstimator.sizeOf(docs);
// if (firstNonSorted(docs,0,docs.length)>=0) throw new RuntimeException("NON SORTED DOCS!!!");
}
@@ -54,11 +62,6 @@ public class SortedIntDocSet extends DocSetBase {
@Override
public int size() { return docs.length; }
- @Override
- public long memSize() {
- return (docs.length<<2)+8;
- }
-
public static int[] zeroInts = new int[0];
public static SortedIntDocSet zero = new SortedIntDocSet(zeroInts);
@@ -785,4 +788,14 @@ public class SortedIntDocSet extends DocSetBase {
protected SortedIntDocSet clone() {
return new SortedIntDocSet(docs.clone());
}
+
+ @Override
+ public long ramBytesUsed() {
+ return ramBytesUsed;
+ }
+
+ @Override
+ public Collection getChildResources() {
+ return Collections.emptyList();
+ }
}
diff --git a/solr/core/src/test/org/apache/solr/search/DocSetPerf.java b/solr/core/src/test/org/apache/solr/search/DocSetPerf.java
index 37c13df4c97..711c8fff213 100644
--- a/solr/core/src/test/org/apache/solr/search/DocSetPerf.java
+++ b/solr/core/src/test/org/apache/solr/search/DocSetPerf.java
@@ -74,7 +74,7 @@ public class DocSetPerf {
String test = args[3].intern();
int iter = Integer.parseInt(args[4]);
- int ret=0;
+ long ret=0;
FixedBitSet[] sets = new FixedBitSet[numSets];
DocSet[] bset = new DocSet[numSets];
@@ -153,7 +153,7 @@ public class DocSetPerf {
if (oper=="intersect") {
DocSet res = a.intersection(b);
- ret += res.memSize();
+ ret += res.ramBytesUsed();
} else if (oper=="intersectSize") {
ret += a.intersectionSize(b);
} else if (oper=="intersectAndSize") {