mirror of
https://github.com/apache/lucene.git
synced 2025-02-09 11:35:14 +00:00
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
|
with a filter of "baz" will internally leapfrog foo,bar,baz as one
|
||||||
conjunction. (Ryan Ernst, Robert Muir, Adrien Grande)
|
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
|
Build
|
||||||
|
|
||||||
* LUCENE-6518: Don't report false thread leaks from IBM J9
|
* 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.SortedMap;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import org.apache.lucene.util.ArrayUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collection of {@link FieldInfo}s (accessible by number or by name).
|
* Collection of {@link FieldInfo}s (accessible by number or by name).
|
||||||
* @lucene.experimental
|
* @lucene.experimental
|
||||||
@ -38,7 +40,10 @@ public class FieldInfos implements Iterable<FieldInfo> {
|
|||||||
private final boolean hasNorms;
|
private final boolean hasNorms;
|
||||||
private final boolean hasDocValues;
|
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 HashMap<String,FieldInfo> byName = new HashMap<>();
|
||||||
private final Collection<FieldInfo> values; // for an unmodifiable iterator
|
private final Collection<FieldInfo> values; // for an unmodifiable iterator
|
||||||
|
|
||||||
@ -54,6 +59,7 @@ public class FieldInfos implements Iterable<FieldInfo> {
|
|||||||
boolean hasNorms = false;
|
boolean hasNorms = false;
|
||||||
boolean hasDocValues = false;
|
boolean hasDocValues = false;
|
||||||
|
|
||||||
|
TreeMap<Integer, FieldInfo> byNumber = new TreeMap<>();
|
||||||
for (FieldInfo info : infos) {
|
for (FieldInfo info : infos) {
|
||||||
if (info.number < 0) {
|
if (info.number < 0) {
|
||||||
throw new IllegalArgumentException("illegal field number: " + info.number + " for field " + info.name);
|
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.hasNorms = hasNorms;
|
||||||
this.hasDocValues = hasDocValues;
|
this.hasDocValues = hasDocValues;
|
||||||
this.values = Collections.unmodifiableCollection(byNumber.values());
|
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 */
|
/** Returns true if any fields have freqs */
|
||||||
@ -123,8 +145,7 @@ public class FieldInfos implements Iterable<FieldInfo> {
|
|||||||
|
|
||||||
/** Returns the number of fields */
|
/** Returns the number of fields */
|
||||||
public int size() {
|
public int size() {
|
||||||
assert byNumber.size() == byName.size();
|
return byName.size();
|
||||||
return byNumber.size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -157,7 +178,14 @@ public class FieldInfos implements Iterable<FieldInfo> {
|
|||||||
if (fieldNumber < 0) {
|
if (fieldNumber < 0) {
|
||||||
throw new IllegalArgumentException("Illegal field number: " + fieldNumber);
|
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 {
|
static final class FieldNumbers {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user