Skip to content

Commit

Permalink
Special case merging ArrayTagSets and TagLists (#986)
Browse files Browse the repository at this point in the history
Special case merging an ArrayTagSet with another to avoid the
overhead of sorting, deduping, and copying. Since an ArrayTagSet
is immutable, already sorted, and deduped, we can skip directly
to merging..

Additionally, add handling for merging of an ArrayTagSet with a
TagList, where we can avoid some extra copying and allocating of
Tags.
  • Loading branch information
kilink authored Sep 11, 2022
1 parent dfb0012 commit 42cc39b
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentMap;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
Expand Down Expand Up @@ -150,6 +151,11 @@ ArrayTagSet addAll(Iterable<Tag> ts) {
checkForNullValues(newTags);
return addAll(newTags, newTags.length);
}
} else if (ts instanceof TagList) {
if (ts instanceof ArrayTagSet) {
return addAll((ArrayTagSet) ts);
}
return addAll((TagList) ts);
} else {
List<Tag> data = new ArrayList<>();
for (Tag t : ts) {
Expand Down Expand Up @@ -210,6 +216,33 @@ private ArrayTagSet addAll(String[] ts, int tsLength) {
}
}

private ArrayTagSet addAll(ArrayTagSet ts) {
if (ts == this || ts.isEmpty()) {
return this;
}
if (isEmpty()) {
return ts;
}
String[] newTags = new String[length + ts.length];
int newLength = merge(newTags, tags, length, ts.tags, ts.length);
return new ArrayTagSet(newTags, newLength);
}

private ArrayTagSet addAll(TagList ts) {
int size = ts.size();

if (size == 0) {
return this;
}
String[] newTags = new String[size * 2];
int j = 0;
for (int i = 0; i < size; i++) {
newTags[j++] = Objects.requireNonNull(ts.getKey(i), "tag keys cannot be null");
newTags[j++] = Objects.requireNonNull(ts.getValue(i), "tag values cannot be null");
}
return addAll(newTags, newTags.length);
}

/** Add a collection of tags to the set. */
ArrayTagSet addAll(Tag[] ts) {
return addAll(ts, ts.length);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,27 @@ public void testMergeTag() {
Assertions.assertEquals(expected, initial.addAll(update));
}

@Test
public void testMergeWithSelf() {
ArrayTagSet tags = ArrayTagSet.create("k1", "v1");
ArrayTagSet updated = tags.addAll(tags);
Assertions.assertSame(tags, updated);
}

@Test
public void testMergeWithEmpty() {
ArrayTagSet tags = ArrayTagSet.create("k1", "v1");
ArrayTagSet updated = tags.addAll(ArrayTagSet.EMPTY);
Assertions.assertSame(tags, updated);
}

@Test
public void testEmptyMergeWithNonEmpty() {
ArrayTagSet tags = ArrayTagSet.create("k1", "v1");
ArrayTagSet updated = ArrayTagSet.EMPTY.addAll(tags);
Assertions.assertSame(tags, updated);
}

@Test
public void testMergeTagWithSameKey() {
ArrayTagSet initial = ArrayTagSet.create("k1", "v1");
Expand Down Expand Up @@ -503,4 +524,53 @@ public void compareToDifferentSizes() {
Assertions.assertEquals(-1, a.compareTo(b));
Assertions.assertEquals(1, b.compareTo(a));
}

@Test
public void mergeTagList() {
TagList tagList = new TagList() {
@Override
public String getKey(int i) {
return "k" + ++i;
}

@Override
public String getValue(int i) {
return "v" + ++i;
}

@Override
public int size() {
return 3;
}
};
ArrayTagSet tags = ArrayTagSet.create("k1", "v1", "k2", "v2");
ArrayTagSet updated = tags.addAll(tagList);
ArrayTagSet expected = ArrayTagSet.create("k1", "v1", "k2", "v2", "k3", "v3");
Assertions.assertEquals(expected, updated);
}

@Test
public void mergeEmptyTagList() {
TagList empty = new TagList() {
@Override
public String getKey(int i) {
throw new IndexOutOfBoundsException();
}

@Override
public String getValue(int i) {
throw new IndexOutOfBoundsException();
}

@Override
public int size() {
return 0;
}
};

ArrayTagSet tags = ArrayTagSet.create("k1", "v1", "k2", "v2");
ArrayTagSet updated = tags.addAll(empty);

Assertions.assertSame(tags, updated);
}
}

0 comments on commit 42cc39b

Please sign in to comment.