Memory optimizations (#505)

* Remove LocatedBlock overhead in LBL map

* Add new space-efficient block map, with thourough testing

* Drop ordering property, add full insertion test

* Add licenses

* Fix mocked platform conflicts

* Disable full block map testing for faster builds

* Re-implement BlockMap with fastutil maps

* Re-write chunk batching to be memory efficient

* Make MultiStageReorder use BlockMap

* Increase LBL load factor, fix long-pack limit detection

* Fix infinite loop in chunk batching

* Save memory in history by cleaning up MSR

* Re-implement LocatedBlockList in BlockMap

* Fix data race with BlockType lazy fields

* Make IDs ALWAYS present, only runtime-consistent. Use for memory efficiency in BlockMap

* Remap inner structure of BlockMap for smaller maps

* Remove containedBlocks fields, not very efficient

* Fix minor de-optimizing bug in stage reorder

* Make long packed y signed

* Add extended Y limit configuration option

* Add licenses

* Store 3 ints for unoptimized BV list

* Add final to BitMath

* Correct int-cast for long-packing
This commit is contained in:
Kenzie Togami
2019-08-12 05:06:40 -07:00
committed by Matthew Miller
parent ec5bc5a3b7
commit f472c20bfb
30 changed files with 2014 additions and 139 deletions

View File

@ -22,10 +22,10 @@ package com.sk89q.worldedit.internal.block;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.registry.BlockRegistry;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Map;
import java.util.BitSet;
import java.util.OptionalInt;
import static com.google.common.base.Preconditions.checkState;
@ -43,19 +43,32 @@ public final class BlockStateIdAccess {
return ASSIGNED_IDS.inverse().get(id);
}
/**
* For platforms that don't have an internal ID system,
* {@link BlockRegistry#getInternalBlockStateId(BlockState)} will return
* {@link OptionalInt#empty()}. In those cases, we will use our own ID system,
* since it's useful for other entries as well.
* @return an unused ID in WorldEdit's ID tracker
*/
private static int provideUnusedWorldEditId() {
return usedIds.nextClearBit(0);
}
private static final BitSet usedIds = new BitSet();
public static void register(BlockState blockState, OptionalInt id) {
if (id.isPresent()) {
int i = id.getAsInt();
BlockState existing = ASSIGNED_IDS.inverse().get(i);
checkState(existing == null || existing == blockState,
"BlockState %s is using the same block ID (%s) as BlockState %s",
blockState, i, existing);
ASSIGNED_IDS.put(blockState, i);
}
int i = id.orElseGet(BlockStateIdAccess::provideUnusedWorldEditId);
BlockState existing = ASSIGNED_IDS.inverse().get(i);
checkState(existing == null || existing == blockState,
"BlockState %s is using the same block ID (%s) as BlockState %s",
blockState, i, existing);
ASSIGNED_IDS.put(blockState, i);
usedIds.set(i);
}
public static void clear() {
ASSIGNED_IDS.clear();
usedIds.clear();
}
private BlockStateIdAccess() {