Improve read performance with different tag

This commit is contained in:
themode 2022-03-24 11:23:16 +01:00
parent 2301ad9976
commit 043c139b91
4 changed files with 72 additions and 3 deletions

View File

@ -178,6 +178,12 @@ public class Tag<T> {
write(nbtCompound, (T) value);
}
final boolean shareValue(@NotNull Tag<?> other) {
// Verify if these 2 tags can share the same cached value
// Key/Default value/Path are ignored
return this == other || this.readFunction == other.readFunction;
}
public static @NotNull Tag<Byte> Byte(@NotNull String key) {
return tag(key, NBTByte::getValue, NBT::Byte);
}

View File

@ -172,6 +172,12 @@ final class TagHandlerImpl implements TagHandler {
this.tag = tag;
this.value = value;
}
NBT updatedNbt() {
NBT nbt = this.nbt;
if (nbt == null) this.nbt = nbt = tag.writeFunction.apply(value);
return nbt;
}
}
private record Cache(Entry<?>[] entries, NBTCompound compound) implements TagReadable {
@ -196,6 +202,10 @@ final class TagHandlerImpl implements TagHandler {
}
if (entry.value instanceof TagHandlerImpl handler) {
entries = handler.entries;
} else if (entry.updatedNbt() instanceof NBTCompound compound) {
var tmp = new TagHandlerImpl();
tmp.updateContent(compound);
entries = tmp.entries;
}
}
}
@ -206,14 +216,13 @@ final class TagHandlerImpl implements TagHandler {
if (value instanceof TagHandlerImpl)
throw new IllegalStateException("Cannot read path-able tag " + tag.getKey());
final Tag entryTag = entry.tag;
if (entryTag == tag) {
if (entryTag.shareValue(tag)) {
// Tag is the same, return the value
//noinspection unchecked
return (T) value;
}
// Value must be parsed from nbt if the tag is different
NBT nbt = entry.nbt;
if (nbt == null) entry.nbt = nbt = (NBT) entryTag.writeFunction.apply(value);
final NBT nbt = entry.updatedNbt();
try {
return tag.readFunction.apply(nbt);
} catch (ClassCastException e) {

View File

@ -0,0 +1,53 @@
package net.minestom.server.tag;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Test tags that can share cached values.
*/
public class TagEqualityTest {
@Test
public void same() {
var tag = Tag.String("test");
assertTrue(tag.shareValue(tag));
}
@Test
public void similar() {
var tag = Tag.String("test");
var tag2 = Tag.String("test");
assertTrue(tag.shareValue(tag2));
}
@Test
public void differentDefault() {
var tag = Tag.String("test").defaultValue("test2");
var tag2 = Tag.String("test").defaultValue("test3");
assertTrue(tag.shareValue(tag2));
}
@Test
public void differentType() {
var tag = Tag.String("test");
var tag2 = Tag.Integer("test");
assertFalse(tag.shareValue(tag2));
}
@Test
public void list() {
var tag = Tag.String("test").list();
assertTrue(tag.shareValue(tag));
}
//@Test
public void similarList() {
// TODO make work
var tag = Tag.String("test").list();
var tag2 = Tag.String("test").list();
assertTrue(tag.shareValue(tag2));
}
}

View File

@ -236,6 +236,7 @@ public class TagPathTest {
}
}
""", handler.asCompound());
assertEquals(5, handler.getTag(tag.path("struct")));
handler.setTag(tag, 5);
assertEqualsSNBT("""