diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/common/trove/ExtTDoubleObjectHashMap.java b/modules/elasticsearch/src/main/java/org/elasticsearch/common/trove/ExtTDoubleObjectHashMap.java new file mode 100644 index 00000000000..9607021e950 --- /dev/null +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/common/trove/ExtTDoubleObjectHashMap.java @@ -0,0 +1,53 @@ +/* + * Licensed to Elastic Search and Shay Banon under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. Elastic Search licenses this + * file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.common.trove; + +import org.elasticsearch.common.trove.map.TDoubleObjectMap; +import org.elasticsearch.common.trove.map.hash.TDoubleObjectHashMap; + +public class ExtTDoubleObjectHashMap extends TDoubleObjectHashMap { + + public ExtTDoubleObjectHashMap() { + } + + public ExtTDoubleObjectHashMap(int initialCapacity) { + super(initialCapacity); + } + + public ExtTDoubleObjectHashMap(int initialCapacity, float loadFactor) { + super(initialCapacity, loadFactor); + } + + public ExtTDoubleObjectHashMap(int initialCapacity, float loadFactor, double noEntryKey) { + super(initialCapacity, loadFactor, noEntryKey); + } + + public ExtTDoubleObjectHashMap(TDoubleObjectMap vtDoubleObjectMap) { + super(vtDoubleObjectMap); + } + + /** + * Internal method to get the actual values associated. Some values might have "null" or no entry + * values. + */ + public Object[] internalValues() { + return this._values; + } +} \ No newline at end of file diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/common/trove/ExtTHashMap.java b/modules/elasticsearch/src/main/java/org/elasticsearch/common/trove/ExtTHashMap.java new file mode 100644 index 00000000000..370e3a11c89 --- /dev/null +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/common/trove/ExtTHashMap.java @@ -0,0 +1,54 @@ +/* + * Licensed to Elastic Search and Shay Banon under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. Elastic Search licenses this + * file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.common.trove; + +import org.elasticsearch.common.trove.map.hash.THashMap; + +import java.util.Map; + +public class ExtTHashMap extends THashMap { + + public ExtTHashMap() { + } + + public ExtTHashMap(int initialCapacity) { + super(initialCapacity); + } + + public ExtTHashMap(int initialCapacity, float loadFactor) { + super(initialCapacity, loadFactor); + } + + public ExtTHashMap(Map kvMap) { + super(kvMap); + } + + public ExtTHashMap(THashMap kvtHashMap) { + super(kvtHashMap); + } + + /** + * Internal method to get the actual values associated. Some values might have "null" or no entry + * values. + */ + public Object[] internalValues() { + return this._values; + } +} \ No newline at end of file diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/common/trove/ExtTLongObjectHashMap.java b/modules/elasticsearch/src/main/java/org/elasticsearch/common/trove/ExtTLongObjectHashMap.java new file mode 100644 index 00000000000..160ee1a9d17 --- /dev/null +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/common/trove/ExtTLongObjectHashMap.java @@ -0,0 +1,53 @@ +/* + * Licensed to Elastic Search and Shay Banon under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. Elastic Search licenses this + * file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.common.trove; + +import org.elasticsearch.common.trove.map.TLongObjectMap; +import org.elasticsearch.common.trove.map.hash.TLongObjectHashMap; + +public class ExtTLongObjectHashMap extends TLongObjectHashMap { + + public ExtTLongObjectHashMap() { + } + + public ExtTLongObjectHashMap(int initialCapacity) { + super(initialCapacity); + } + + public ExtTLongObjectHashMap(int initialCapacity, float loadFactor) { + super(initialCapacity, loadFactor); + } + + public ExtTLongObjectHashMap(int initialCapacity, float loadFactor, long noEntryKey) { + super(initialCapacity, loadFactor, noEntryKey); + } + + public ExtTLongObjectHashMap(TLongObjectMap vtLongObjectMap) { + super(vtLongObjectMap); + } + + /** + * Internal method to get the actual values associated. Some values might have "null" or no entry + * values. + */ + public Object[] internalValues() { + return this._values; + } +} \ No newline at end of file diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacet.java b/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacet.java index c701236b59d..f360e3933ff 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacet.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/TermsStatsFacet.java @@ -60,6 +60,13 @@ public interface TermsStatsFacet extends Facet, Iterable COUNT((byte) 0, new Comparator() { @Override public int compare(Entry o1, Entry o2) { + // push nulls to the end + if (o1 == null) { + return 1; + } + if (o2 == null) { + return -1; + } int i = o2.count() - o1.count(); if (i == 0) { i = o2.term().compareTo(o1.term()); @@ -76,6 +83,13 @@ public interface TermsStatsFacet extends Facet, Iterable REVERSE_COUNT((byte) 1, new Comparator() { @Override public int compare(Entry o1, Entry o2) { + // push nulls to the end + if (o1 == null) { + return 1; + } + if (o2 == null) { + return -1; + } return -COUNT.comparator().compare(o1, o2); } }), @@ -85,6 +99,13 @@ public interface TermsStatsFacet extends Facet, Iterable TERM((byte) 2, new Comparator() { @Override public int compare(Entry o1, Entry o2) { + // push nulls to the end + if (o1 == null) { + return 1; + } + if (o2 == null) { + return -1; + } int i = o1.compareTo(o2); if (i == 0) { i = COUNT.comparator().compare(o1, o2); @@ -98,12 +119,26 @@ public interface TermsStatsFacet extends Facet, Iterable REVERSE_TERM((byte) 3, new Comparator() { @Override public int compare(Entry o1, Entry o2) { + // push nulls to the end + if (o1 == null) { + return 1; + } + if (o2 == null) { + return -1; + } return -TERM.comparator().compare(o1, o2); } }), TOTAL((byte) 4, new Comparator() { @Override public int compare(Entry o1, Entry o2) { + // push nulls to the end + if (o1 == null) { + return 1; + } + if (o2 == null) { + return -1; + } if (o2.total() < o1.total()) { return -1; } else if (o2.total() == o1.total()) { @@ -116,6 +151,13 @@ public interface TermsStatsFacet extends Facet, Iterable REVERSE_TOTAL((byte) 5, new Comparator() { @Override public int compare(Entry o1, Entry o2) { + // push nulls to the end + if (o1 == null) { + return 1; + } + if (o2 == null) { + return -1; + } return -TOTAL.comparator().compare(o1, o2); } }); diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/doubles/InternalTermsStatsDoubleFacet.java b/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/doubles/InternalTermsStatsDoubleFacet.java index f2d40e14dc2..6a73e58d9b9 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/doubles/InternalTermsStatsDoubleFacet.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/doubles/InternalTermsStatsDoubleFacet.java @@ -19,12 +19,11 @@ package org.elasticsearch.search.facet.termsstats.doubles; -import org.elasticsearch.common.collect.BoundedTreeSet; import org.elasticsearch.common.collect.ImmutableList; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.thread.ThreadLocals; -import org.elasticsearch.common.trove.map.hash.THashMap; +import org.elasticsearch.common.trove.ExtTDoubleObjectHashMap; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilderString; import org.elasticsearch.search.facet.Facet; @@ -176,9 +175,9 @@ public class InternalTermsStatsDoubleFacet extends InternalTermsStatsFacet { return missingCount(); } - private static ThreadLocal>> aggregateCache = new ThreadLocal>>() { - @Override protected ThreadLocals.CleanableValue> initialValue() { - return new ThreadLocals.CleanableValue>(new THashMap()); + private static ThreadLocal>> aggregateCache = new ThreadLocal>>() { + @Override protected ThreadLocals.CleanableValue> initialValue() { + return new ThreadLocals.CleanableValue>(new ExtTDoubleObjectHashMap()); } }; @@ -195,31 +194,39 @@ public class InternalTermsStatsDoubleFacet extends InternalTermsStatsFacet { return facets.get(0); } int missing = 0; - THashMap map = aggregateCache.get().get(); + ExtTDoubleObjectHashMap map = aggregateCache.get().get(); map.clear(); for (Facet facet : facets) { InternalTermsStatsDoubleFacet tsFacet = (InternalTermsStatsDoubleFacet) facet; missing += tsFacet.missing; for (Entry entry : tsFacet) { DoubleEntry doubleEntry = (DoubleEntry) entry; - DoubleEntry current = map.get(doubleEntry.term()); + DoubleEntry current = map.get(doubleEntry.term); if (current != null) { current.count += doubleEntry.count; current.total += doubleEntry.total; } else { - map.put(doubleEntry.term(), doubleEntry); + map.put(doubleEntry.term, doubleEntry); } } } // sort if (requiredSize == 0) { // all terms - DoubleEntry[] entries1 = map.values().toArray(new DoubleEntry[map.size()]); + DoubleEntry[] entries1 = map.values(new DoubleEntry[map.size()]); Arrays.sort(entries1, comparatorType.comparator()); return new InternalTermsStatsDoubleFacet(name, comparatorType, requiredSize, Arrays.asList(entries1), missing); } else { - TreeSet ordered = new BoundedTreeSet(comparatorType.comparator(), requiredSize); - ordered.addAll(map.values()); + Object[] values = map.internalValues(); + Arrays.sort(values, (Comparator) comparatorType.comparator()); + List ordered = new ArrayList(); + for (int i = 0; i < requiredSize; i++) { + DoubleEntry value = (DoubleEntry) values[i]; + if (value == null) { + break; + } + ordered.add(value); + } return new InternalTermsStatsDoubleFacet(name, comparatorType, requiredSize, ordered, missing); } } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/doubles/TermsStatsDoubleFacetCollector.java b/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/doubles/TermsStatsDoubleFacetCollector.java index 6bdcbff8e84..d8558403342 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/doubles/TermsStatsDoubleFacetCollector.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/doubles/TermsStatsDoubleFacetCollector.java @@ -22,10 +22,10 @@ package org.elasticsearch.search.facet.termsstats.doubles; import org.apache.lucene.index.IndexReader; import org.apache.lucene.search.Scorer; import org.elasticsearch.ElasticSearchIllegalArgumentException; -import org.elasticsearch.common.collect.BoundedTreeSet; import org.elasticsearch.common.collect.ImmutableList; +import org.elasticsearch.common.collect.Lists; import org.elasticsearch.common.thread.ThreadLocals; -import org.elasticsearch.common.trove.map.hash.TDoubleObjectHashMap; +import org.elasticsearch.common.trove.ExtTDoubleObjectHashMap; import org.elasticsearch.index.cache.field.data.FieldDataCache; import org.elasticsearch.index.field.data.FieldDataType; import org.elasticsearch.index.field.data.NumericFieldData; @@ -38,10 +38,7 @@ import org.elasticsearch.search.facet.termsstats.TermsStatsFacet; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.Map; -import java.util.TreeSet; +import java.util.*; public class TermsStatsDoubleFacetCollector extends AbstractFacetCollector { @@ -69,7 +66,7 @@ public class TermsStatsDoubleFacetCollector extends AbstractFacetCollector { private int missing = 0; - private final TDoubleObjectHashMap entries; + private final ExtTDoubleObjectHashMap entries; public TermsStatsDoubleFacetCollector(String facetName, String keyFieldName, String valueFieldName, int size, TermsStatsFacet.ComparatorType comparatorType, SearchContext context, String scriptLang, String script, Map params) { @@ -164,8 +161,18 @@ public class TermsStatsDoubleFacetCollector extends AbstractFacetCollector { return new InternalTermsStatsDoubleFacet(facetName, comparatorType, 0 /* indicates all terms*/, entries.valueCollection(), missing); } // we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards - TreeSet ordered = new BoundedTreeSet(comparatorType.comparator(), size * numberOfShards); - ordered.addAll(entries.valueCollection()); + Object[] values = entries.internalValues(); + Arrays.sort(values, (Comparator) comparatorType.comparator()); + + int limit = size * numberOfShards; + List ordered = Lists.newArrayList(); + for (int i = 0; i < limit; i++) { + InternalTermsStatsDoubleFacet.DoubleEntry value = (InternalTermsStatsDoubleFacet.DoubleEntry) values[i]; + if (value == null) { + break; + } + ordered.add(value); + } // that's fine to push here, this thread will be released AFTER the entries have either been serialized // or processed @@ -174,27 +181,27 @@ public class TermsStatsDoubleFacetCollector extends AbstractFacetCollector { } - static TDoubleObjectHashMap popFacets() { - Deque> deque = cache.get().get(); + static ExtTDoubleObjectHashMap popFacets() { + Deque> deque = cache.get().get(); if (deque.isEmpty()) { - deque.add(new TDoubleObjectHashMap()); + deque.add(new ExtTDoubleObjectHashMap()); } - TDoubleObjectHashMap facets = deque.pollFirst(); + ExtTDoubleObjectHashMap facets = deque.pollFirst(); facets.clear(); return facets; } - static void pushFacets(TDoubleObjectHashMap facets) { + static void pushFacets(ExtTDoubleObjectHashMap facets) { facets.clear(); - Deque> deque = cache.get().get(); + Deque> deque = cache.get().get(); if (deque != null) { deque.add(facets); } } - static ThreadLocal>>> cache = new ThreadLocal>>>() { - @Override protected ThreadLocals.CleanableValue>> initialValue() { - return new ThreadLocals.CleanableValue>>(new ArrayDeque>()); + static ThreadLocal>>> cache = new ThreadLocal>>>() { + @Override protected ThreadLocals.CleanableValue>> initialValue() { + return new ThreadLocals.CleanableValue>>(new ArrayDeque>()); } }; } \ No newline at end of file diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/longs/InternalTermsStatsLongFacet.java b/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/longs/InternalTermsStatsLongFacet.java index 23fd025998b..69d6d4e08e4 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/longs/InternalTermsStatsLongFacet.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/longs/InternalTermsStatsLongFacet.java @@ -19,12 +19,11 @@ package org.elasticsearch.search.facet.termsstats.longs; -import org.elasticsearch.common.collect.BoundedTreeSet; import org.elasticsearch.common.collect.ImmutableList; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.thread.ThreadLocals; -import org.elasticsearch.common.trove.map.hash.THashMap; +import org.elasticsearch.common.trove.ExtTLongObjectHashMap; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilderString; import org.elasticsearch.search.facet.Facet; @@ -176,9 +175,9 @@ public class InternalTermsStatsLongFacet extends InternalTermsStatsFacet { return missingCount(); } - private static ThreadLocal>> aggregateCache = new ThreadLocal>>() { - @Override protected ThreadLocals.CleanableValue> initialValue() { - return new ThreadLocals.CleanableValue>(new THashMap()); + private static ThreadLocal>> aggregateCache = new ThreadLocal>>() { + @Override protected ThreadLocals.CleanableValue> initialValue() { + return new ThreadLocals.CleanableValue>(new ExtTLongObjectHashMap()); } }; @@ -195,31 +194,39 @@ public class InternalTermsStatsLongFacet extends InternalTermsStatsFacet { return facets.get(0); } int missing = 0; - THashMap map = aggregateCache.get().get(); + ExtTLongObjectHashMap map = aggregateCache.get().get(); map.clear(); for (Facet facet : facets) { InternalTermsStatsLongFacet tsFacet = (InternalTermsStatsLongFacet) facet; missing += tsFacet.missing; for (Entry entry : tsFacet) { LongEntry longEntry = (LongEntry) entry; - LongEntry current = map.get(longEntry.term()); + LongEntry current = map.get(longEntry.term); if (current != null) { current.count += longEntry.count; current.total += longEntry.total; } else { - map.put(longEntry.term(), longEntry); + map.put(longEntry.term, longEntry); } } } // sort if (requiredSize == 0) { // all terms - LongEntry[] entries1 = map.values().toArray(new LongEntry[map.size()]); + LongEntry[] entries1 = map.values(new LongEntry[map.size()]); Arrays.sort(entries1, comparatorType.comparator()); return new InternalTermsStatsLongFacet(name, comparatorType, requiredSize, Arrays.asList(entries1), missing); } else { - TreeSet ordered = new BoundedTreeSet(comparatorType.comparator(), requiredSize); - ordered.addAll(map.values()); + Object[] values = map.internalValues(); + Arrays.sort(values, (Comparator) comparatorType.comparator()); + List ordered = new ArrayList(); + for (int i = 0; i < requiredSize; i++) { + LongEntry value = (LongEntry) values[i]; + if (value == null) { + break; + } + ordered.add(value); + } return new InternalTermsStatsLongFacet(name, comparatorType, requiredSize, ordered, missing); } } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/longs/TermsStatsLongFacetCollector.java b/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/longs/TermsStatsLongFacetCollector.java index f0845294347..f853db44d85 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/longs/TermsStatsLongFacetCollector.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/longs/TermsStatsLongFacetCollector.java @@ -22,10 +22,10 @@ package org.elasticsearch.search.facet.termsstats.longs; import org.apache.lucene.index.IndexReader; import org.apache.lucene.search.Scorer; import org.elasticsearch.ElasticSearchIllegalArgumentException; -import org.elasticsearch.common.collect.BoundedTreeSet; import org.elasticsearch.common.collect.ImmutableList; +import org.elasticsearch.common.collect.Lists; import org.elasticsearch.common.thread.ThreadLocals; -import org.elasticsearch.common.trove.map.hash.TLongObjectHashMap; +import org.elasticsearch.common.trove.ExtTLongObjectHashMap; import org.elasticsearch.index.cache.field.data.FieldDataCache; import org.elasticsearch.index.field.data.FieldDataType; import org.elasticsearch.index.field.data.NumericFieldData; @@ -38,10 +38,7 @@ import org.elasticsearch.search.facet.termsstats.TermsStatsFacet; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.Map; -import java.util.TreeSet; +import java.util.*; public class TermsStatsLongFacetCollector extends AbstractFacetCollector { @@ -69,7 +66,7 @@ public class TermsStatsLongFacetCollector extends AbstractFacetCollector { private int missing = 0; - private final TLongObjectHashMap entries; + private final ExtTLongObjectHashMap entries; public TermsStatsLongFacetCollector(String facetName, String keyFieldName, String valueFieldName, int size, TermsStatsFacet.ComparatorType comparatorType, SearchContext context, String scriptLang, String script, Map params) { @@ -163,10 +160,20 @@ public class TermsStatsLongFacetCollector extends AbstractFacetCollector { // all terms, just return the collection, we will sort it on the way back return new InternalTermsStatsLongFacet(facetName, comparatorType, 0 /* indicates all terms*/, entries.valueCollection(), missing); } - // we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards - TreeSet ordered = new BoundedTreeSet(comparatorType.comparator(), size * numberOfShards); - ordered.addAll(entries.valueCollection()); + // we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards + Object[] values = entries.internalValues(); + Arrays.sort(values, (Comparator) comparatorType.comparator()); + + int limit = size * numberOfShards; + List ordered = Lists.newArrayList(); + for (int i = 0; i < limit; i++) { + InternalTermsStatsLongFacet.LongEntry value = (InternalTermsStatsLongFacet.LongEntry) values[i]; + if (value == null) { + break; + } + ordered.add(value); + } // that's fine to push here, this thread will be released AFTER the entries have either been serialized // or processed pushFacets(entries); @@ -174,27 +181,27 @@ public class TermsStatsLongFacetCollector extends AbstractFacetCollector { } - static TLongObjectHashMap popFacets() { - Deque> deque = cache.get().get(); + static ExtTLongObjectHashMap popFacets() { + Deque> deque = cache.get().get(); if (deque.isEmpty()) { - deque.add(new TLongObjectHashMap()); + deque.add(new ExtTLongObjectHashMap()); } - TLongObjectHashMap facets = deque.pollFirst(); + ExtTLongObjectHashMap facets = deque.pollFirst(); facets.clear(); return facets; } - static void pushFacets(TLongObjectHashMap facets) { + static void pushFacets(ExtTLongObjectHashMap facets) { facets.clear(); - Deque> deque = cache.get().get(); + Deque> deque = cache.get().get(); if (deque != null) { deque.add(facets); } } - static ThreadLocal>>> cache = new ThreadLocal>>>() { - @Override protected ThreadLocals.CleanableValue>> initialValue() { - return new ThreadLocals.CleanableValue>>(new ArrayDeque>()); + static ThreadLocal>>> cache = new ThreadLocal>>>() { + @Override protected ThreadLocals.CleanableValue>> initialValue() { + return new ThreadLocals.CleanableValue>>(new ArrayDeque>()); } }; } \ No newline at end of file diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/strings/InternalTermsStatsStringFacet.java b/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/strings/InternalTermsStatsStringFacet.java index c088e58e9ce..d223c2e5c59 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/strings/InternalTermsStatsStringFacet.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/strings/InternalTermsStatsStringFacet.java @@ -19,12 +19,11 @@ package org.elasticsearch.search.facet.termsstats.strings; -import org.elasticsearch.common.collect.BoundedTreeSet; import org.elasticsearch.common.collect.ImmutableList; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.thread.ThreadLocals; -import org.elasticsearch.common.trove.map.hash.THashMap; +import org.elasticsearch.common.trove.ExtTHashMap; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilderString; import org.elasticsearch.search.facet.Facet; @@ -175,9 +174,9 @@ public class InternalTermsStatsStringFacet extends InternalTermsStatsFacet { return missingCount(); } - private static ThreadLocal>> aggregateCache = new ThreadLocal>>() { - @Override protected ThreadLocals.CleanableValue> initialValue() { - return new ThreadLocals.CleanableValue>(new THashMap()); + private static ThreadLocal>> aggregateCache = new ThreadLocal>>() { + @Override protected ThreadLocals.CleanableValue> initialValue() { + return new ThreadLocals.CleanableValue>(new ExtTHashMap()); } }; @@ -194,7 +193,7 @@ public class InternalTermsStatsStringFacet extends InternalTermsStatsFacet { return facets.get(0); } int missing = 0; - THashMap map = aggregateCache.get().get(); + ExtTHashMap map = aggregateCache.get().get(); map.clear(); for (Facet facet : facets) { InternalTermsStatsStringFacet tsFacet = (InternalTermsStatsStringFacet) facet; @@ -217,8 +216,16 @@ public class InternalTermsStatsStringFacet extends InternalTermsStatsFacet { Arrays.sort(entries1, comparatorType.comparator()); return new InternalTermsStatsStringFacet(name, comparatorType, requiredSize, Arrays.asList(entries1), missing); } else { - TreeSet ordered = new BoundedTreeSet(comparatorType.comparator(), requiredSize); - ordered.addAll(map.values()); + Object[] values = map.internalValues(); + Arrays.sort(values, (Comparator) comparatorType.comparator()); + List ordered = new ArrayList(); + for (int i = 0; i < requiredSize; i++) { + StringEntry value = (StringEntry) values[i]; + if (value == null) { + break; + } + ordered.add(value); + } return new InternalTermsStatsStringFacet(name, comparatorType, requiredSize, ordered, missing); } } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/strings/TermsStatsStringFacetCollector.java b/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/strings/TermsStatsStringFacetCollector.java index 4138e60d42a..37027398108 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/strings/TermsStatsStringFacetCollector.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/search/facet/termsstats/strings/TermsStatsStringFacetCollector.java @@ -22,10 +22,10 @@ package org.elasticsearch.search.facet.termsstats.strings; import org.apache.lucene.index.IndexReader; import org.apache.lucene.search.Scorer; import org.elasticsearch.ElasticSearchIllegalArgumentException; -import org.elasticsearch.common.collect.BoundedTreeSet; import org.elasticsearch.common.collect.ImmutableList; +import org.elasticsearch.common.collect.Lists; import org.elasticsearch.common.thread.ThreadLocals; -import org.elasticsearch.common.trove.map.hash.THashMap; +import org.elasticsearch.common.trove.ExtTHashMap; import org.elasticsearch.index.cache.field.data.FieldDataCache; import org.elasticsearch.index.field.data.FieldData; import org.elasticsearch.index.field.data.FieldDataType; @@ -39,10 +39,7 @@ import org.elasticsearch.search.facet.termsstats.TermsStatsFacet; import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.Map; -import java.util.TreeSet; +import java.util.*; public class TermsStatsStringFacetCollector extends AbstractFacetCollector { @@ -70,7 +67,7 @@ public class TermsStatsStringFacetCollector extends AbstractFacetCollector { private int missing = 0; - private final THashMap entries; + private final ExtTHashMap entries; public TermsStatsStringFacetCollector(String facetName, String keyFieldName, String valueFieldName, int size, TermsStatsFacet.ComparatorType comparatorType, SearchContext context, String scriptLang, String script, Map params) { @@ -165,8 +162,18 @@ public class TermsStatsStringFacetCollector extends AbstractFacetCollector { return new InternalTermsStatsStringFacet(facetName, comparatorType, 0 /* indicates all terms*/, entries.values(), missing); } // we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards - TreeSet ordered = new BoundedTreeSet(comparatorType.comparator(), size * numberOfShards); - ordered.addAll(entries.values()); + Object[] values = entries.internalValues(); + Arrays.sort(values, (Comparator) comparatorType.comparator()); + + List ordered = Lists.newArrayList(); + int limit = size * numberOfShards; + for (int i = 0; i < limit; i++) { + InternalTermsStatsStringFacet.StringEntry value = (InternalTermsStatsStringFacet.StringEntry) values[i]; + if (value == null) { + break; + } + ordered.add(value); + } // that's fine to push here, this thread will be released AFTER the entries have either been serialized // or processed @@ -175,27 +182,27 @@ public class TermsStatsStringFacetCollector extends AbstractFacetCollector { } - static THashMap popFacets() { - Deque> deque = cache.get().get(); + static ExtTHashMap popFacets() { + Deque> deque = cache.get().get(); if (deque.isEmpty()) { - deque.add(new THashMap()); + deque.add(new ExtTHashMap()); } - THashMap facets = deque.pollFirst(); + ExtTHashMap facets = deque.pollFirst(); facets.clear(); return facets; } - static void pushFacets(THashMap facets) { + static void pushFacets(ExtTHashMap facets) { facets.clear(); - Deque> deque = cache.get().get(); + Deque> deque = cache.get().get(); if (deque != null) { deque.add(facets); } } - static ThreadLocal>>> cache = new ThreadLocal>>>() { - @Override protected ThreadLocals.CleanableValue>> initialValue() { - return new ThreadLocals.CleanableValue>>(new ArrayDeque>()); + static ThreadLocal>>> cache = new ThreadLocal>>>() { + @Override protected ThreadLocals.CleanableValue>> initialValue() { + return new ThreadLocals.CleanableValue>>(new ArrayDeque>()); } }; } \ No newline at end of file