improve numeric stream analysis performance
This commit is contained in:
parent
3c3d01347e
commit
5c08271e74
|
@ -7,7 +7,7 @@
|
|||
</pattern>
|
||||
</extension>
|
||||
<option name="MAIN_CLASS_NAME" value="org.elasticsearch.bootstrap.Bootstrap" />
|
||||
<option name="VM_PARAMETERS" value="-server -Xmx1g -Des-foreground=yes -XX:+AggressiveOpts -XX:+UseParNewGC -XX:+UseConcMarkSweepGCa" />
|
||||
<option name="VM_PARAMETERS" value="-server -Xmx1g -Des-foreground=yes -XX:+AggressiveOpts -XX:+UseParNewGC -XX:+UseConcMarkSweepGC" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
package org.elasticsearch.index.mapper.xcontent;
|
||||
|
||||
import org.apache.lucene.analysis.TokenStream;
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.document.Fieldable;
|
||||
import org.apache.lucene.search.Filter;
|
||||
|
@ -152,15 +151,7 @@ public class BoostFieldMapper extends NumberFieldMapper<Float> implements org.el
|
|||
return null;
|
||||
}
|
||||
context.doc().setBoost(value);
|
||||
return new CustomNumericField(names.indexName(), indexed(), stored() ? Numbers.floatToBytes(value) : null) {
|
||||
@Override public TokenStream tokenStreamValue() {
|
||||
if (indexed()) {
|
||||
return popCachedStream(precisionStep).setFloatValue(value);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
return new FloatFieldMapper.CustomFloatNumericField(this, value);
|
||||
}
|
||||
|
||||
private float parseFloatValue(ParseContext context) throws IOException {
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
package org.elasticsearch.index.mapper.xcontent;
|
||||
|
||||
import org.apache.lucene.analysis.TokenStream;
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.document.Fieldable;
|
||||
import org.apache.lucene.search.Filter;
|
||||
|
@ -200,15 +199,7 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
|
|||
}
|
||||
|
||||
final long value = parseStringValue(dateAsString);
|
||||
return new CustomNumericField(names.indexName(), indexed(), stored() ? Numbers.longToBytes(value) : null) {
|
||||
@Override public TokenStream tokenStreamValue() {
|
||||
if (indexed()) {
|
||||
return popCachedStream(precisionStep).setLongValue(value);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
return new LongFieldMapper.CustomLongNumericField(this, value);
|
||||
}
|
||||
|
||||
@Override public FieldDataType fieldDataType() {
|
||||
|
|
|
@ -182,16 +182,7 @@ public class DoubleFieldMapper extends NumberFieldMapper<Double> {
|
|||
}
|
||||
}
|
||||
|
||||
final double fValue = value;
|
||||
return new CustomNumericField(names.indexName(), indexed(), stored() ? Numbers.doubleToBytes(fValue) : null) {
|
||||
@Override public TokenStream tokenStreamValue() {
|
||||
if (indexed()) {
|
||||
return popCachedStream(precisionStep).setDoubleValue(fValue);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
return new CustomDoubleNumericField(this, value);
|
||||
}
|
||||
|
||||
@Override public FieldDataType fieldDataType() {
|
||||
|
@ -240,4 +231,24 @@ public class DoubleFieldMapper extends NumberFieldMapper<Double> {
|
|||
builder.field("include_in_all", includeInAll);
|
||||
}
|
||||
}
|
||||
|
||||
public static class CustomDoubleNumericField extends CustomNumericField {
|
||||
|
||||
private final double number;
|
||||
|
||||
private final NumberFieldMapper mapper;
|
||||
|
||||
public CustomDoubleNumericField(NumberFieldMapper mapper, double number) {
|
||||
super(mapper, mapper.stored() ? Numbers.doubleToBytes(number) : null);
|
||||
this.mapper = mapper;
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
@Override public TokenStream tokenStreamValue() {
|
||||
if (isIndexed) {
|
||||
return mapper.popCachedStream().setDoubleValue(number);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -181,16 +181,7 @@ public class FloatFieldMapper extends NumberFieldMapper<Float> {
|
|||
}
|
||||
}
|
||||
|
||||
final float fValue = value;
|
||||
return new CustomNumericField(names.indexName(), indexed(), stored() ? Numbers.floatToBytes(fValue) : null) {
|
||||
@Override public TokenStream tokenStreamValue() {
|
||||
if (indexed()) {
|
||||
return popCachedStream(precisionStep).setFloatValue(fValue);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
return new CustomFloatNumericField(this, value);
|
||||
}
|
||||
|
||||
@Override public FieldDataType fieldDataType() {
|
||||
|
@ -240,4 +231,24 @@ public class FloatFieldMapper extends NumberFieldMapper<Float> {
|
|||
builder.field("include_in_all", includeInAll);
|
||||
}
|
||||
}
|
||||
|
||||
public static class CustomFloatNumericField extends CustomNumericField {
|
||||
|
||||
private final float number;
|
||||
|
||||
private final NumberFieldMapper mapper;
|
||||
|
||||
public CustomFloatNumericField(NumberFieldMapper mapper, float number) {
|
||||
super(mapper, mapper.stored() ? Numbers.floatToBytes(number) : null);
|
||||
this.mapper = mapper;
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
@Override public TokenStream tokenStreamValue() {
|
||||
if (isIndexed) {
|
||||
return mapper.popCachedStream().setFloatValue(number);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -181,16 +181,7 @@ public class IntegerFieldMapper extends NumberFieldMapper<Integer> {
|
|||
}
|
||||
}
|
||||
|
||||
final int fValue = value;
|
||||
return new CustomNumericField(names.indexName(), indexed(), stored() ? Numbers.intToBytes(fValue) : null) {
|
||||
@Override public TokenStream tokenStreamValue() {
|
||||
if (indexed()) {
|
||||
return popCachedStream(precisionStep).setIntValue(fValue);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
return new CustomIntegerNumericField(this, value);
|
||||
}
|
||||
|
||||
@Override public FieldDataType fieldDataType() {
|
||||
|
@ -239,4 +230,24 @@ public class IntegerFieldMapper extends NumberFieldMapper<Integer> {
|
|||
builder.field("include_in_all", includeInAll);
|
||||
}
|
||||
}
|
||||
|
||||
public static class CustomIntegerNumericField extends CustomNumericField {
|
||||
|
||||
private final int number;
|
||||
|
||||
private final NumberFieldMapper mapper;
|
||||
|
||||
public CustomIntegerNumericField(NumberFieldMapper mapper, int number) {
|
||||
super(mapper, mapper.stored() ? Numbers.intToBytes(number) : null);
|
||||
this.mapper = mapper;
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
@Override public TokenStream tokenStreamValue() {
|
||||
if (isIndexed) {
|
||||
return mapper.popCachedStream().setIntValue(number);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,17 +180,7 @@ public class LongFieldMapper extends NumberFieldMapper<Long> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
final long fValue = value;
|
||||
return new CustomNumericField(names.indexName(), indexed(), stored() ? Numbers.longToBytes(value) : null) {
|
||||
@Override public TokenStream tokenStreamValue() {
|
||||
if (indexed()) {
|
||||
return popCachedStream(precisionStep).setLongValue(fValue);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
return new CustomLongNumericField(this, value);
|
||||
}
|
||||
|
||||
@Override public FieldDataType fieldDataType() {
|
||||
|
@ -239,4 +229,24 @@ public class LongFieldMapper extends NumberFieldMapper<Long> {
|
|||
builder.field("include_in_all", includeInAll);
|
||||
}
|
||||
}
|
||||
|
||||
public static class CustomLongNumericField extends CustomNumericField {
|
||||
|
||||
private final long number;
|
||||
|
||||
private final NumberFieldMapper mapper;
|
||||
|
||||
public CustomLongNumericField(NumberFieldMapper mapper, long number) {
|
||||
super(mapper, mapper.stored() ? Numbers.longToBytes(number) : null);
|
||||
this.mapper = mapper;
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
@Override public TokenStream tokenStreamValue() {
|
||||
if (isIndexed) {
|
||||
return mapper.popCachedStream().setLongValue(number);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,25 +20,19 @@
|
|||
package org.elasticsearch.index.mapper.xcontent;
|
||||
|
||||
import org.apache.lucene.analysis.NumericTokenStream;
|
||||
import org.apache.lucene.analysis.TokenStream;
|
||||
import org.apache.lucene.document.AbstractField;
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.document.Fieldable;
|
||||
import org.apache.lucene.search.Filter;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.util.NumericUtils;
|
||||
import org.apache.lucene.util.StringHelper;
|
||||
import org.elasticsearch.common.thread.ThreadLocals;
|
||||
import org.elasticsearch.common.trove.TIntObjectHashMap;
|
||||
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
||||
import org.elasticsearch.index.cache.field.data.FieldDataCache;
|
||||
import org.elasticsearch.index.field.data.FieldDataType;
|
||||
import org.elasticsearch.index.mapper.MergeMappingException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
/**
|
||||
* @author kimchy (shay.banon)
|
||||
|
@ -85,16 +79,16 @@ public abstract class NumberFieldMapper<T extends Number> extends AbstractFieldM
|
|||
}
|
||||
}
|
||||
|
||||
private static final ThreadLocal<ThreadLocals.CleanableValue<TIntObjectHashMap<Deque<CachedNumericTokenStream>>>> cachedStreams = new ThreadLocal<ThreadLocals.CleanableValue<TIntObjectHashMap<Deque<CachedNumericTokenStream>>>>() {
|
||||
@Override protected ThreadLocals.CleanableValue<TIntObjectHashMap<Deque<CachedNumericTokenStream>>> initialValue() {
|
||||
return new ThreadLocals.CleanableValue<TIntObjectHashMap<Deque<CachedNumericTokenStream>>>(new TIntObjectHashMap<Deque<CachedNumericTokenStream>>());
|
||||
}
|
||||
};
|
||||
|
||||
protected int precisionStep;
|
||||
|
||||
protected Boolean includeInAll;
|
||||
|
||||
private ThreadLocal<ThreadLocals.CleanableValue<NumericTokenStream>> tokenStream = new ThreadLocal<ThreadLocals.CleanableValue<NumericTokenStream>>() {
|
||||
@Override protected ThreadLocals.CleanableValue<NumericTokenStream> initialValue() {
|
||||
return new ThreadLocals.CleanableValue<NumericTokenStream>(new NumericTokenStream(precisionStep));
|
||||
}
|
||||
};
|
||||
|
||||
protected NumberFieldMapper(Names names, int precisionStep,
|
||||
Field.Index index, Field.Store store,
|
||||
float boost, boolean omitNorms, boolean omitTermFreqAndPositions,
|
||||
|
@ -176,98 +170,22 @@ public abstract class NumberFieldMapper<T extends Number> extends AbstractFieldM
|
|||
|
||||
@Override public abstract FieldDataType fieldDataType();
|
||||
|
||||
/**
|
||||
* Removes a cached numeric token stream. The stream will be returned to the cached once it is used
|
||||
* since it implements the end method.
|
||||
*/
|
||||
protected CachedNumericTokenStream popCachedStream(int precisionStep) {
|
||||
Deque<CachedNumericTokenStream> deque = cachedStreams.get().get().get(precisionStep);
|
||||
if (deque == null) {
|
||||
deque = new ArrayDeque<CachedNumericTokenStream>();
|
||||
cachedStreams.get().get().put(precisionStep, deque);
|
||||
deque.add(new CachedNumericTokenStream(new NumericTokenStream(precisionStep), precisionStep));
|
||||
}
|
||||
if (deque.isEmpty()) {
|
||||
deque.add(new CachedNumericTokenStream(new NumericTokenStream(precisionStep), precisionStep));
|
||||
}
|
||||
return deque.pollFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper around a numeric stream allowing to reuse it by implementing the end method which returns
|
||||
* this stream back to the thread local cache.
|
||||
*/
|
||||
protected static final class CachedNumericTokenStream extends TokenStream {
|
||||
|
||||
private final int precisionStep;
|
||||
|
||||
private final NumericTokenStream numericTokenStream;
|
||||
|
||||
public CachedNumericTokenStream(NumericTokenStream numericTokenStream, int precisionStep) {
|
||||
super(numericTokenStream);
|
||||
this.numericTokenStream = numericTokenStream;
|
||||
this.precisionStep = precisionStep;
|
||||
}
|
||||
|
||||
public void end() throws IOException {
|
||||
numericTokenStream.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the input TokenStream.
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
numericTokenStream.close();
|
||||
TIntObjectHashMap<Deque<CachedNumericTokenStream>> cached = cachedStreams.get().get();
|
||||
if (cached != null) {
|
||||
Deque<CachedNumericTokenStream> cachedDeque = cached.get(precisionStep);
|
||||
if (cachedDeque != null) {
|
||||
cachedDeque.add(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the filter as well as the input TokenStream.
|
||||
*/
|
||||
public void reset() throws IOException {
|
||||
numericTokenStream.reset();
|
||||
}
|
||||
|
||||
@Override public boolean incrementToken() throws IOException {
|
||||
return numericTokenStream.incrementToken();
|
||||
}
|
||||
|
||||
public CachedNumericTokenStream setIntValue(int value) {
|
||||
numericTokenStream.setIntValue(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CachedNumericTokenStream setLongValue(long value) {
|
||||
numericTokenStream.setLongValue(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CachedNumericTokenStream setFloatValue(float value) {
|
||||
numericTokenStream.setFloatValue(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CachedNumericTokenStream setDoubleValue(double value) {
|
||||
numericTokenStream.setDoubleValue(value);
|
||||
return this;
|
||||
}
|
||||
protected NumericTokenStream popCachedStream() {
|
||||
return tokenStream.get().get();
|
||||
}
|
||||
|
||||
// used to we can use a numeric field in a document that is then parsed twice!
|
||||
protected abstract static class CustomNumericField extends AbstractField {
|
||||
public abstract static class CustomNumericField extends AbstractField {
|
||||
|
||||
public CustomNumericField(String name, boolean indexed, byte[] value) {
|
||||
this.name = StringHelper.intern(name); // field names are interned
|
||||
protected final NumberFieldMapper mapper;
|
||||
|
||||
public CustomNumericField(NumberFieldMapper mapper, byte[] value) {
|
||||
this.mapper = mapper;
|
||||
this.name = mapper.names().indexName();
|
||||
fieldsData = value;
|
||||
|
||||
isIndexed = indexed;
|
||||
isTokenized = indexed;
|
||||
isIndexed = mapper.indexed();
|
||||
isTokenized = mapper.indexed();
|
||||
omitTermFreqAndPositions = true;
|
||||
omitNorms = true;
|
||||
|
||||
|
|
|
@ -180,16 +180,7 @@ public class ShortFieldMapper extends NumberFieldMapper<Short> {
|
|||
}
|
||||
}
|
||||
}
|
||||
final short fValue = value;
|
||||
return new CustomNumericField(names.indexName(), indexed(), stored() ? Numbers.shortToBytes(fValue) : null) {
|
||||
@Override public TokenStream tokenStreamValue() {
|
||||
if (indexed()) {
|
||||
return popCachedStream(precisionStep).setIntValue(fValue);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
return new CustomShortNumericField(this, value);
|
||||
}
|
||||
|
||||
@Override public FieldDataType fieldDataType() {
|
||||
|
@ -238,4 +229,24 @@ public class ShortFieldMapper extends NumberFieldMapper<Short> {
|
|||
builder.field("include_in_all", includeInAll);
|
||||
}
|
||||
}
|
||||
|
||||
public static class CustomShortNumericField extends CustomNumericField {
|
||||
|
||||
private final short number;
|
||||
|
||||
private final NumberFieldMapper mapper;
|
||||
|
||||
public CustomShortNumericField(NumberFieldMapper mapper, short number) {
|
||||
super(mapper, mapper.stored() ? Numbers.shortToBytes(number) : null);
|
||||
this.mapper = mapper;
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
@Override public TokenStream tokenStreamValue() {
|
||||
if (isIndexed) {
|
||||
return mapper.popCachedStream().setIntValue(number);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,7 +20,6 @@
|
|||
package org.elasticsearch.index.mapper.xcontent.ip;
|
||||
|
||||
import org.apache.lucene.analysis.NumericTokenStream;
|
||||
import org.apache.lucene.analysis.TokenStream;
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.document.Fieldable;
|
||||
import org.apache.lucene.search.Filter;
|
||||
|
@ -40,10 +39,7 @@ import org.elasticsearch.index.cache.field.data.FieldDataCache;
|
|||
import org.elasticsearch.index.field.data.FieldDataType;
|
||||
import org.elasticsearch.index.mapper.MapperParsingException;
|
||||
import org.elasticsearch.index.mapper.MergeMappingException;
|
||||
import org.elasticsearch.index.mapper.xcontent.MergeContext;
|
||||
import org.elasticsearch.index.mapper.xcontent.NumberFieldMapper;
|
||||
import org.elasticsearch.index.mapper.xcontent.ParseContext;
|
||||
import org.elasticsearch.index.mapper.xcontent.XContentMapper;
|
||||
import org.elasticsearch.index.mapper.xcontent.*;
|
||||
import org.elasticsearch.index.search.NumericRangeFieldDataFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -219,15 +215,7 @@ public class IpFieldMapper extends NumberFieldMapper<Long> {
|
|||
}
|
||||
|
||||
final long value = ipToLong(ipAsString);
|
||||
return new CustomNumericField(names.indexName(), indexed(), stored() ? Numbers.longToBytes(value) : null) {
|
||||
@Override public TokenStream tokenStreamValue() {
|
||||
if (indexed()) {
|
||||
return popCachedStream(precisionStep).setLongValue(value);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
return new LongFieldMapper.CustomLongNumericField(this, value);
|
||||
}
|
||||
|
||||
@Override public FieldDataType fieldDataType() {
|
||||
|
|
Loading…
Reference in New Issue