RiftRegistry partial parallelization of serialization

This commit is contained in:
CreepyCre 2021-02-25 20:01:24 +01:00
parent b45632b466
commit a2704a165a
2 changed files with 60 additions and 49 deletions

View file

@ -40,7 +40,7 @@ public class SchematicGenerator extends LazyPocketGenerator{
private String id; private String id;
private Identifier templateID; private Identifier templateID;
BlockPlacementType placementType = BlockPlacementType.SECTION_NO_UPDATE; private BlockPlacementType placementType = BlockPlacementType.SECTION_NO_UPDATE;
private final List<RiftBlockEntity> rifts = new ArrayList<>(); private final List<RiftBlockEntity> rifts = new ArrayList<>();
private BlockPos origin; private BlockPos origin;
@ -84,7 +84,7 @@ public class SchematicGenerator extends LazyPocketGenerator{
int[] originInts = tag.getIntArray("origin"); int[] originInts = tag.getIntArray("origin");
this.origin = new BlockPos(originInts[0], originInts[1], originInts[2]); this.origin = new BlockPos(originInts[0], originInts[1], originInts[2]);
} }
if (tag.contains("placement_type")) placementType = BlockPlacementType.getFromId(tag.getString("placement_type")); if (tag.contains("placement_type", NbtType.STRING)) placementType = BlockPlacementType.getFromId(tag.getString("placement_type"));
return this; return this;
} }

View file

@ -1,13 +1,11 @@
package org.dimdev.dimdoors.rift.registry; package org.dimdev.dimdoors.rift.registry;
import java.util.Collection; import java.util.*;
import java.util.Collections; import java.util.concurrent.CompletableFuture;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import net.fabricmc.fabric.api.util.NbtType;
import net.minecraft.util.Pair;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.util.GraphUtils; import org.dimdev.dimdoors.util.GraphUtils;
@ -37,30 +35,31 @@ public class RiftRegistry {
protected Map<UUID, PlayerRiftPointer> lastPrivatePocketExits = new HashMap<>(); // Player UUID -> last rift used to enter pocket protected Map<UUID, PlayerRiftPointer> lastPrivatePocketExits = new HashMap<>(); // Player UUID -> last rift used to enter pocket
protected Map<UUID, PlayerRiftPointer> overworldRifts = new HashMap<>(); // Player UUID -> rift used to exit the overworld protected Map<UUID, PlayerRiftPointer> overworldRifts = new HashMap<>(); // Player UUID -> rift used to exit the overworld
// TODO: async
public static RiftRegistry fromTag(Map<RegistryKey<World>, PocketDirectory> pocketRegistry, CompoundTag nbt) { public static RiftRegistry fromTag(Map<RegistryKey<World>, PocketDirectory> pocketRegistry, CompoundTag nbt) {
// Read rifts in this dimension // Read rifts in this dimension
RiftRegistry riftRegistry = new RiftRegistry(); RiftRegistry riftRegistry = new RiftRegistry();
ListTag riftsNBT = (ListTag) nbt.get("rifts"); ListTag riftsNBT = nbt.getList("rifts", NbtType.COMPOUND);
for (Tag riftNBT : riftsNBT) { CompletableFuture<List<Rift>> futureRifts = CompletableFuture.supplyAsync(() -> riftsNBT.parallelStream().unordered().map(CompoundTag.class::cast).map(Rift::fromTag).collect(Collectors.toList()));
Rift rift = Rift.fromTag((CompoundTag) riftNBT);
ListTag pocketsNBT = nbt.getList("pockets", NbtType.COMPOUND);
CompletableFuture<List<PocketEntrancePointer>> futurePockets = CompletableFuture.supplyAsync(() -> pocketsNBT.stream().map(CompoundTag.class::cast).map(PocketEntrancePointer::fromTag).collect(Collectors.toList()));
futureRifts.join().forEach(rift -> {
riftRegistry.graph.addVertex(rift); riftRegistry.graph.addVertex(rift);
riftRegistry.uuidMap.put(rift.id, rift); riftRegistry.uuidMap.put(rift.id, rift);
riftRegistry.locationMap.put(rift.location, rift); riftRegistry.locationMap.put(rift.location, rift);
} });
ListTag pocketsNBT = (ListTag) nbt.get("pockets"); futurePockets.join().forEach(pocket -> {
for (Tag pocketNBT : pocketsNBT) {
PocketEntrancePointer pocket = PocketEntrancePointer.fromTag((CompoundTag) pocketNBT);
riftRegistry.graph.addVertex(pocket); riftRegistry.graph.addVertex(pocket);
riftRegistry.uuidMap.put(pocket.id, pocket); riftRegistry.uuidMap.put(pocket.id, pocket);
riftRegistry.pocketEntranceMap.put(pocketRegistry.get(pocket.world).getPocket(pocket.pocketId), pocket); riftRegistry.pocketEntranceMap.put(pocketRegistry.get(pocket.world).getPocket(pocket.pocketId), pocket);
} });
// Read the connections between links that have a source or destination in this dimension // Read the connections between links that have a source or destination in this dimension
ListTag linksNBT = (ListTag) nbt.get("links"); ListTag linksNBT = nbt.getList("links", NbtType.COMPOUND);
for (Tag linkNBT : linksNBT) { for (Tag linkNBT : linksNBT) {
RegistryVertex from = riftRegistry.uuidMap.get(((CompoundTag) linkNBT).getUuid("from")); RegistryVertex from = riftRegistry.uuidMap.get(((CompoundTag) linkNBT).getUuid("from"));
RegistryVertex to = riftRegistry.uuidMap.get(((CompoundTag) linkNBT).getUuid("to")); RegistryVertex to = riftRegistry.uuidMap.get(((CompoundTag) linkNBT).getUuid("to"));
@ -70,51 +69,62 @@ public class RiftRegistry {
} }
} }
riftRegistry.lastPrivatePocketEntrances = riftRegistry.readPlayerRiftPointers((ListTag) nbt.get("lastPrivatePocketEntrances")); riftRegistry.lastPrivatePocketEntrances = riftRegistry.readPlayerRiftPointers(nbt.getList("last_private_pocket_entrances", NbtType.COMPOUND));
riftRegistry.lastPrivatePocketExits = riftRegistry.readPlayerRiftPointers((ListTag) nbt.get("lastPrivatePocketExits")); riftRegistry.lastPrivatePocketExits = riftRegistry.readPlayerRiftPointers(nbt.getList("last_private_pocket_exits", NbtType.COMPOUND));
riftRegistry.overworldRifts = riftRegistry.readPlayerRiftPointers((ListTag) nbt.get("overworldRifts")); riftRegistry.overworldRifts = riftRegistry.readPlayerRiftPointers(nbt.getList("overworld_rifts", NbtType.COMPOUND));
return riftRegistry; return riftRegistry;
} }
// TODO: async
public CompoundTag toTag() { public CompoundTag toTag() {
CompoundTag tag = new CompoundTag(); CompoundTag tag = new CompoundTag();
// Write rifts in this dimension // Write rifts in this dimension
ListTag riftsNBT = new ListTag(); CompletableFuture<Pair<ListTag, ListTag>> futureRiftsAndPocketsNBT = CompletableFuture.supplyAsync(() -> {
ListTag pocketsNBT = new ListTag(); Map<Boolean, List<RegistryVertex>> vertices = this.graph.vertexSet().parallelStream().unordered().filter(vertex -> vertex instanceof Rift || vertex instanceof PocketEntrancePointer)
for (RegistryVertex vertex : this.graph.vertexSet()) { .collect(Collectors.partitioningBy(Rift.class::isInstance));
CompoundTag vertexNBT = RegistryVertex.toTag(vertex);
if (vertex instanceof Rift) { CompletableFuture<List<CompoundTag>> futureRiftsNBT = CompletableFuture.supplyAsync(() -> vertices.get(true).parallelStream().map(RegistryVertex::toTag).collect(Collectors.toList()));
riftsNBT.add(vertexNBT); CompletableFuture<List<CompoundTag>> futurePocketsNBT = CompletableFuture.supplyAsync(() -> vertices.get(false).parallelStream().map(RegistryVertex::toTag).collect(Collectors.toList()));
} else if (vertex instanceof PocketEntrancePointer) {
pocketsNBT.add(vertexNBT); ListTag riftsNBT = new ListTag();
} else if (!(vertex instanceof PlayerRiftPointer)) { ListTag pocketsNBT = new ListTag();
throw new RuntimeException("Unsupported registry vertex type " + vertex.getClass().getName());
} riftsNBT.addAll(futureRiftsNBT.join());
} pocketsNBT.addAll(futurePocketsNBT.join());
tag.put("rifts", riftsNBT);
tag.put("pockets", pocketsNBT); return new Pair<>(riftsNBT, pocketsNBT);
});
// Write the connections between links that have a source or destination in this dimension // Write the connections between links that have a source or destination in this dimension
ListTag linksNBT = new ListTag(); CompletableFuture<ListTag> futureLinksNBT = CompletableFuture.supplyAsync(() -> {
for (DefaultEdge edge : this.graph.edgeSet()) { ListTag linksNBT = new ListTag();
RegistryVertex from = this.graph.getEdgeSource(edge); for (DefaultEdge edge : this.graph.edgeSet()) {
RegistryVertex to = this.graph.getEdgeTarget(edge); RegistryVertex from = this.graph.getEdgeSource(edge);
CompoundTag linkNBT = new CompoundTag(); RegistryVertex to = this.graph.getEdgeTarget(edge);
linkNBT.putUuid("from", from.id); CompoundTag linkNBT = new CompoundTag();
linkNBT.putUuid("to", to.id); linkNBT.putUuid("from", from.id);
linksNBT.add(linkNBT); linkNBT.putUuid("to", to.id);
} linksNBT.add(linkNBT);
tag.put("links", linksNBT); }
return linksNBT;
});
// Subregistries are written automatically when the worlds are saved. // Subregistries are written automatically when the worlds are saved.
tag.put("lastPrivatePocketEntrances", this.writePlayerRiftPointers(this.lastPrivatePocketEntrances)); tag.put("last_private_pocket_entrances", this.writePlayerRiftPointers(this.lastPrivatePocketEntrances));
tag.put("lastPrivatePocketExits", this.writePlayerRiftPointers(this.lastPrivatePocketExits)); tag.put("last_private_pocket_exits", this.writePlayerRiftPointers(this.lastPrivatePocketExits));
tag.put("overworldRifts", this.writePlayerRiftPointers(this.overworldRifts)); tag.put("overworld_rifts", this.writePlayerRiftPointers(this.overworldRifts));
Pair<ListTag, ListTag> riftsAndPocketsNBT = futureRiftsAndPocketsNBT.join();
tag.put("rifts", riftsAndPocketsNBT.getLeft());
tag.put("pockets", riftsAndPocketsNBT.getRight());
tag.put("links", futureLinksNBT.join());
return tag; return tag;
} }
// TODO: parallelization
private Map<UUID, PlayerRiftPointer> readPlayerRiftPointers(ListTag tag) { private Map<UUID, PlayerRiftPointer> readPlayerRiftPointers(ListTag tag) {
Map<UUID, PlayerRiftPointer> pointerMap = new HashMap<>(); Map<UUID, PlayerRiftPointer> pointerMap = new HashMap<>();
for (Tag entryNBT : tag) { for (Tag entryNBT : tag) {
@ -129,6 +139,7 @@ public class RiftRegistry {
return pointerMap; return pointerMap;
} }
// TODO: parallelization
private ListTag writePlayerRiftPointers(Map<UUID, PlayerRiftPointer> playerRiftPointerMap) { private ListTag writePlayerRiftPointers(Map<UUID, PlayerRiftPointer> playerRiftPointerMap) {
ListTag pointers = new ListTag(); ListTag pointers = new ListTag();
for (Map.Entry<UUID, PlayerRiftPointer> entry : playerRiftPointerMap.entrySet()) { for (Map.Entry<UUID, PlayerRiftPointer> entry : playerRiftPointerMap.entrySet()) {