mirror of https://github.com/apache/lucene.git
LUCENE-6325: use array for number -> FieldInfo lookup, except in very sparse cases
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1687789 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
75c60be660
commit
42fdbbeb95
|
@ -225,6 +225,10 @@ Optimizations
|
|||
with a filter of "baz" will internally leapfrog foo,bar,baz as one
|
||||
conjunction. (Ryan Ernst, Robert Muir, Adrien Grande)
|
||||
|
||||
* LUCENE-6325: Reduce RAM usage of FieldInfos, and speed up lookup by
|
||||
number, by using an array instead of TreeMap except in very sparse
|
||||
cases (Robert Muir, Mike McCandless)
|
||||
|
||||
Build
|
||||
|
||||
* LUCENE-6518: Don't report false thread leaks from IBM J9
|
||||
|
|
|
@ -25,6 +25,8 @@ import java.util.Map;
|
|||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.apache.lucene.util.ArrayUtil;
|
||||
|
||||
/**
|
||||
* Collection of {@link FieldInfo}s (accessible by number or by name).
|
||||
* @lucene.experimental
|
||||
|
@ -38,7 +40,10 @@ public class FieldInfos implements Iterable<FieldInfo> {
|
|||
private final boolean hasNorms;
|
||||
private final boolean hasDocValues;
|
||||
|
||||
private final SortedMap<Integer,FieldInfo> byNumber = new TreeMap<>();
|
||||
// used only by fieldInfo(int)
|
||||
private final FieldInfo[] byNumberTable; // contiguous
|
||||
private final SortedMap<Integer,FieldInfo> byNumberMap; // sparse
|
||||
|
||||
private final HashMap<String,FieldInfo> byName = new HashMap<>();
|
||||
private final Collection<FieldInfo> values; // for an unmodifiable iterator
|
||||
|
||||
|
@ -54,6 +59,7 @@ public class FieldInfos implements Iterable<FieldInfo> {
|
|||
boolean hasNorms = false;
|
||||
boolean hasDocValues = false;
|
||||
|
||||
TreeMap<Integer, FieldInfo> byNumber = new TreeMap<>();
|
||||
for (FieldInfo info : infos) {
|
||||
if (info.number < 0) {
|
||||
throw new IllegalArgumentException("illegal field number: " + info.number + " for field " + info.name);
|
||||
|
@ -84,6 +90,22 @@ public class FieldInfos implements Iterable<FieldInfo> {
|
|||
this.hasNorms = hasNorms;
|
||||
this.hasDocValues = hasDocValues;
|
||||
this.values = Collections.unmodifiableCollection(byNumber.values());
|
||||
Integer max = byNumber.isEmpty() ? null : Collections.max(byNumber.keySet());
|
||||
|
||||
// Only usee TreeMap in the very sparse case (< 1/16th of the numbers are used),
|
||||
// because TreeMap uses ~ 64 (32 bit JVM) or 120 (64 bit JVM w/o compressed oops)
|
||||
// overall bytes per entry, but array uses 4 (32 bit JMV) or 8
|
||||
// (64 bit JVM w/o compressed oops):
|
||||
if (max != null && max < ArrayUtil.MAX_ARRAY_LENGTH && max < 16L*byNumber.size()) {
|
||||
byNumberMap = null;
|
||||
byNumberTable = new FieldInfo[max+1];
|
||||
for (Map.Entry<Integer,FieldInfo> entry : byNumber.entrySet()) {
|
||||
byNumberTable[entry.getKey()] = entry.getValue();
|
||||
}
|
||||
} else {
|
||||
byNumberMap = byNumber;
|
||||
byNumberTable = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns true if any fields have freqs */
|
||||
|
@ -123,8 +145,7 @@ public class FieldInfos implements Iterable<FieldInfo> {
|
|||
|
||||
/** Returns the number of fields */
|
||||
public int size() {
|
||||
assert byNumber.size() == byName.size();
|
||||
return byNumber.size();
|
||||
return byName.size();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -157,7 +178,14 @@ public class FieldInfos implements Iterable<FieldInfo> {
|
|||
if (fieldNumber < 0) {
|
||||
throw new IllegalArgumentException("Illegal field number: " + fieldNumber);
|
||||
}
|
||||
return byNumber.get(fieldNumber);
|
||||
if (byNumberTable != null) {
|
||||
if (fieldNumber >= byNumberTable.length) {
|
||||
return null;
|
||||
}
|
||||
return byNumberTable[fieldNumber];
|
||||
} else {
|
||||
return byNumberMap.get(fieldNumber);
|
||||
}
|
||||
}
|
||||
|
||||
static final class FieldNumbers {
|
||||
|
|
Loading…
Reference in New Issue