PERFORMANCE: Optimizetagging API paths

Fixes #7821
This commit is contained in:
Armin 2017-07-26 17:09:41 +02:00 committed by Armin Braun
parent 669be49408
commit 8919210fbe
2 changed files with 52 additions and 23 deletions

View file

@ -1,6 +1,7 @@
package org.logstash; package org.logstash;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import org.jruby.RubyArray; import org.jruby.RubyArray;
import org.jruby.runtime.builtin.IRubyObject; import org.jruby.runtime.builtin.IRubyObject;
@ -11,11 +12,11 @@ public final class ConvertedList extends ArrayList<Object> {
private static final long serialVersionUID = 1396291343595074238L; private static final long serialVersionUID = 1396291343595074238L;
private ConvertedList(final int size) { ConvertedList(final int size) {
super(size); super(size);
} }
public static ConvertedList newFromList(List<Object> list) { public static ConvertedList newFromList(final Collection<?> list) {
ConvertedList array = new ConvertedList(list.size()); ConvertedList array = new ConvertedList(list.size());
for (Object item : list) { for (Object item : list) {

View file

@ -2,7 +2,6 @@ package org.logstash;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -137,8 +136,7 @@ public final class Event implements Cloneable, Queueable {
} }
public Object getField(String reference) { public Object getField(String reference) {
Object val = getUnconvertedField(reference); return Javafier.deep(getUnconvertedField(reference));
return Javafier.deep(val);
} }
public Object getUnconvertedField(String reference) { public Object getUnconvertedField(String reference) {
@ -331,33 +329,63 @@ public final class Event implements Cloneable, Queueable {
return null; return null;
} }
public void tag(String tag) { public void tag(final String tag) {
List<Object> tags; final Object tags = Javafier.deep(accessors.get("tags"));
Object _tags = this.getField("tags");
// short circuit the null case where we know we won't need deduplication step below at the end // short circuit the null case where we know we won't need deduplication step below at the end
if (_tags == null) { if (tags == null) {
setField("tags", Arrays.asList(tag)); initTag(tag);
return;
}
// assign to tags var the proper List of either the existing _tags List or a new List containing whatever non-List item was in the tags field
if (_tags instanceof List) {
tags = (List<Object>) _tags;
} else { } else {
// tags field has a value but not in a List, convert in into a List existingTag(tags, tag);
tags = new ArrayList<>();
tags.add(_tags);
} }
}
// now make sure the tags list does not already contain the tag /**
* Branch of {@link Event#tag(String)} that handles adding the first tag to this event.
* @param tag
*/
private void initTag(final String tag) {
final ConvertedList list = new ConvertedList(1);
list.add(new StringBiValue(tag));
accessors.set("tags", list);
}
/**
* Branch of {@link Event#tag(String)} that handles adding to existing tags.
* @param tags Existing Tag(s)
* @param tag Tag to add
*/
private void existingTag(final Object tags, final String tag) {
if (tags instanceof List) {
appendTag((List<String>) tags, tag);
} else {
scalarTagFallback((String) tags, tag);
}
}
/**
* Merge the given tag into the given list of existing tags if the list doesn't already contain
* the tag.
* @param tags Existing tag list
* @param tag Tag to add
*/
private void appendTag(final List<String> tags, final String tag) {
// TODO: we should eventually look into using alternate data structures to do more efficient dedup but that will require properly defining the tagging API too // TODO: we should eventually look into using alternate data structures to do more efficient dedup but that will require properly defining the tagging API too
if (!tags.contains(tag)) { if (!tags.contains(tag)) {
tags.add(tag); tags.add(tag);
accessors.set("tags", ConvertedList.newFromList(tags));
} }
}
// set that back as a proper BiValue /**
this.setField("tags", tags); * Fallback for {@link Event#tag(String)} in case "tags" was populated by just a String value
* and needs to be converted to a list before appending to it.
* @param existing Existing Tag
* @param tag Tag to add
*/
private void scalarTagFallback(final String existing, final String tag) {
final List<String> tags = new ArrayList<>(2);
tags.add(existing);
appendTag(tags, tag);
} }
@Override @Override