diff options
author | Jon Bratseth <bratseth@oath.com> | 2018-05-11 19:10:58 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-11 19:10:58 +0200 |
commit | 40e9964ea6f7e9940aebd45591822cb7982a914d (patch) | |
tree | ed9b0986dbe39e57c55f003679a07fbf9acc42a9 /container-search/src/main/java/com/yahoo/search/rendering | |
parent | cf80ff1b7ce08cd3fdfd8c789de45da02ffba5c9 (diff) |
Revert "Revert "Bratseth/allocation free hit field traversal""
Diffstat (limited to 'container-search/src/main/java/com/yahoo/search/rendering')
3 files changed, 49 insertions, 71 deletions
diff --git a/container-search/src/main/java/com/yahoo/search/rendering/DefaultRenderer.java b/container-search/src/main/java/com/yahoo/search/rendering/DefaultRenderer.java index bae1185d6a9..2d69a262f15 100644 --- a/container-search/src/main/java/com/yahoo/search/rendering/DefaultRenderer.java +++ b/container-search/src/main/java/com/yahoo/search/rendering/DefaultRenderer.java @@ -185,28 +185,19 @@ public final class DefaultRenderer extends AsynchronousSectionedRenderer<Result> private void renderHitFields(XMLWriter writer, Hit hit) { renderSyntheticRelevanceField(writer, hit); - for (Iterator<Map.Entry<String, Object>> it = hit.fieldIterator(); it.hasNext(); ) { - renderField(writer, hit, it); - } - } - - private void renderField(XMLWriter writer, Hit hit, Iterator<Map.Entry<String, Object>> it) { - renderGenericField(writer, hit, it.next()); + hit.forEachField((name, value) -> renderField(writer, name, value)); } - private void renderGenericField(XMLWriter writer, Hit hit, Map.Entry<String, Object> entry) { - String fieldName = entry.getKey(); - - // skip depending on hit type - if (fieldName.startsWith("$")) return; // Don't render fields that start with $ // TODO: Move to should render + private void renderField(XMLWriter writer, String name, Object value) { + if (name.startsWith("$")) return; - writeOpenFieldElement(writer, fieldName); - renderFieldContent(writer, hit, fieldName); + writeOpenFieldElement(writer, name); + renderFieldContent(writer, value); writeCloseFieldElement(writer); } - private void renderFieldContent(XMLWriter writer, Hit hit, String fieldName) { - writer.escapedContent(asXML(hit.getField(fieldName)), false); + private void renderFieldContent(XMLWriter writer, Object value) { + writer.escapedContent(asXML(value), false); } private String asXML(Object value) { diff --git a/container-search/src/main/java/com/yahoo/search/rendering/JsonRenderer.java b/container-search/src/main/java/com/yahoo/search/rendering/JsonRenderer.java index 34b02b1bee8..6c7018317c3 100644 --- a/container-search/src/main/java/com/yahoo/search/rendering/JsonRenderer.java +++ b/container-search/src/main/java/com/yahoo/search/rendering/JsonRenderer.java @@ -14,7 +14,7 @@ import com.yahoo.document.datatypes.FieldValue; import com.yahoo.document.datatypes.StringFieldValue; import com.yahoo.document.datatypes.TensorFieldValue; import com.yahoo.document.json.JsonWriter; -import com.yahoo.prelude.fastsearch.FastHit; +import com.yahoo.lang.MutableBoolean; import com.yahoo.processing.Response; import com.yahoo.processing.execution.Execution.Trace; import com.yahoo.processing.rendering.AsynchronousSectionedRenderer; @@ -49,6 +49,7 @@ import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; +import java.io.UncheckedIOException; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.StandardCharsets; @@ -472,14 +473,14 @@ public class JsonRenderer extends AsynchronousSectionedRenderer<Result> { return ! (hit instanceof DefaultErrorHit); } - private boolean fieldsStart(boolean hasFieldsField) throws IOException { - if (hasFieldsField) return true; + private void fieldsStart(MutableBoolean hasFieldsField) throws IOException { + if (hasFieldsField.get()) return; generator.writeObjectFieldStart(FIELDS); - return true; + hasFieldsField.set(true); } - private void fieldsEnd(boolean hasFieldsField) throws IOException { - if (!hasFieldsField) return; + private void fieldsEnd(MutableBoolean hasFieldsField) throws IOException { + if ( ! hasFieldsField.get()) return; generator.writeEndObject(); } @@ -508,39 +509,37 @@ public class JsonRenderer extends AsynchronousSectionedRenderer<Result> { } private void renderAllFields(Hit hit) throws IOException { - boolean hasFieldsField = false; - - hasFieldsField |= renderTotalHitCount(hit, hasFieldsField); - hasFieldsField |= renderStandardFields(hit, hasFieldsField); + MutableBoolean hasFieldsField = new MutableBoolean(false); + renderTotalHitCount(hit, hasFieldsField); + renderStandardFields(hit, hasFieldsField); fieldsEnd(hasFieldsField); } - private boolean renderStandardFields(Hit hit, boolean initialHasFieldsField) throws IOException { - boolean hasFieldsField = initialHasFieldsField; - for (String fieldName : hit.fieldKeys()) { - if (!shouldRender(fieldName, hit)) continue; - - // We can't look at the size of fieldKeys() and know whether we need - // the fields object, as all fields may be hidden. - hasFieldsField |= fieldsStart(hasFieldsField); - renderField(fieldName, hit); - } - return hasFieldsField; + private void renderStandardFields(Hit hit, MutableBoolean hasFieldsField) { + hit.forEachField((name, value) -> { + try { + if (shouldRender(name, value)) { + fieldsStart(hasFieldsField); + renderField(name, value); + } + } + catch (IOException e) { + throw new UncheckedIOException(e); + } + }); } - private boolean shouldRender(String fieldName, Hit hit) { + private boolean shouldRender(String name, Object value) { if (debugRendering) return true; - if (fieldName.startsWith(VESPA_HIDDEN_FIELD_PREFIX)) return false; + if (name.startsWith(VESPA_HIDDEN_FIELD_PREFIX)) return false; - Object field = hit.getField(fieldName); - - if (field instanceof CharSequence && ((CharSequence) field).length() == 0) return false; + if (value instanceof CharSequence && ((CharSequence) value).length() == 0) return false; // StringFieldValue cannot hold a null, so checking length directly is OK: - if (field instanceof StringFieldValue && ((StringFieldValue) field).getString().isEmpty()) return false; + if (value instanceof StringFieldValue && ((StringFieldValue) value).getString().isEmpty()) return false; - if (field instanceof NanNumber) return false; + if (value instanceof NanNumber) return false; return true; } @@ -607,17 +606,16 @@ public class JsonRenderer extends AsynchronousSectionedRenderer<Result> { return (id instanceof RawBucketId ? Arrays.toString(((RawBucketId) id).getTo()) : id.getTo()).toString(); } - private boolean renderTotalHitCount(Hit hit, boolean hasFieldsField) throws IOException { - if ( ! (getRecursionLevel() == 1 && hit instanceof HitGroup)) return false; + private void renderTotalHitCount(Hit hit, MutableBoolean hasFieldsField) throws IOException { + if ( ! (getRecursionLevel() == 1 && hit instanceof HitGroup)) return; fieldsStart(hasFieldsField); generator.writeNumberField(TOTAL_COUNT, getResult().getTotalHitCount()); - return true; } - private void renderField(String fieldName, Hit hit) throws IOException { - generator.writeFieldName(fieldName); - renderFieldContents(hit.getField(fieldName)); + private void renderField(String name, Object value) throws IOException { + generator.writeFieldName(name); + renderFieldContents(value); } private void renderFieldContents(Object field) throws IOException { diff --git a/container-search/src/main/java/com/yahoo/search/rendering/SyncDefaultRenderer.java b/container-search/src/main/java/com/yahoo/search/rendering/SyncDefaultRenderer.java index dc72061e224..08599540cb1 100644 --- a/container-search/src/main/java/com/yahoo/search/rendering/SyncDefaultRenderer.java +++ b/container-search/src/main/java/com/yahoo/search/rendering/SyncDefaultRenderer.java @@ -271,25 +271,19 @@ public final class SyncDefaultRenderer extends Renderer { private void renderHitFields(XMLWriter writer, Hit hit) { renderSyntheticRelevanceField(writer, hit); - for (Iterator<Map.Entry<String, Object>> it = hit.fieldIterator(); it.hasNext(); ) { - renderField(writer, hit, it); - } + hit.forEachField((name, value) -> renderField(writer, name, value)); } - private void renderField(XMLWriter writer, Hit hit, Iterator<Map.Entry<String, Object>> it) { - Map.Entry<String, Object> entry = it.next(); - String fieldName = entry.getKey(); - - if ( ! shouldRenderField(hit, fieldName)) return; - if (fieldName.startsWith("$")) return; // Don't render fields that start with $ // TODO: Move to should render + private void renderField(XMLWriter writer, String name, Object value) { + if (name.startsWith("$")) return; - writeOpenFieldElement(writer, fieldName); - renderFieldContent(writer, hit, fieldName); + writeOpenFieldElement(writer, name); + renderFieldContent(writer, value); writeCloseFieldElement(writer); } - private void renderFieldContent(XMLWriter writer, Hit hit, String fieldName) { - writer.escapedContent(asXML(hit.getField(fieldName)), false); + private void renderFieldContent(XMLWriter writer, Object value) { + writer.escapedContent(asXML(value), false); } private String asXML(Object value) { @@ -304,10 +298,10 @@ public final class SyncDefaultRenderer extends Renderer { } private void renderSyntheticRelevanceField(XMLWriter writer, Hit hit) { - final String relevancyFieldName = "relevancy"; - final Relevance relevance = hit.getRelevance(); + String relevancyFieldName = "relevancy"; + Relevance relevance = hit.getRelevance(); - if (shouldRenderField(hit, relevancyFieldName) && relevance != null) { + if (relevance != null) { renderSimpleField(writer, relevancyFieldName, relevance); } } @@ -332,11 +326,6 @@ public final class SyncDefaultRenderer extends Renderer { writer.closeStartTag(); } - private boolean shouldRenderField(Hit hit, String relevancyFieldName) { - // skip depending on hit type - return true; - } - private void renderHitAttributes(XMLWriter writer, Hit hit) { writer.attribute(TYPE, hit.types().stream().collect(Collectors.joining(" "))); if (hit.getRelevance() != null) { |