Lithium (Fabric/NeoForge)

Lithium (Fabric/NeoForge)

36M Downloads

Optimize VoxelShapes.combine for jigsaw structures

TelepathicGrunt opened this issue ยท 2 comments

commented

So I was stress testing my jigsaw structures by spawning a ton of structures and I noticed that while everything works great, the chunk loading is significantly slowed. So I decided to see what the bottleneck is and it turns out, it's pretty much nearly entirely just VoxelShapes.combine. In the profiler pictur ebelow you will see I was using my own StructurePoolBasedGenerator class which is a copy of vanilla's with some changes but even vanilla suffers from the same issue if you make every chunk spawn a larger village. The vanilla code is at StructurePoolBasedGenerator$StructurePoolGenerator line 244

mutableObject4.setValue(
  VoxelShapes.combine(
     (VoxelShape)mutableObject4.getValue(), 
     VoxelShapes.cuboid(Box.from(blockBox4)), 
     BooleanBiFunction.ONLY_FIRST
   )
);

The profiler to show that VoxelShapes.combine takes up the majority of worldgen time over everything else. (This is with Lithium on so even Lithium's current optimizations to VoxelShapes class isn't helping much)
image

What is happening at that line is the jigsaw structure piece is now determined that it will spawn. And so it takes the structure's current VoxelShape of its boundaries and merges the new piece's bounding box into that VoxelShape to create a larger and more complex shape that encompasses the structure pieces in a tight fit. Now with jigsaw structures like bastions or villages, there can be a huge number of individual pieces that has to be merged into the overall structure VoxelShape. And custom structures can get even larger and have even more branches which would explode the VoxelShapes.combine method even more. The more pieces a structure has, the worse the issue becomes I believe.

That's why I think this could be an interesting target for Lithium to optimize. Maybe by redirecting just that VoxelShapes.combine method for jigsaw structures, a better method could be used that is solely optimized for adding new bounding boxes to a complex shape? Just an idea.

I tried to look into how VoxelShapes.combine works and my brain imploded lol

commented

Lithium has a related optimization for the entity nether portal positioning code now, if applicable we may be able to do something similar here.

commented

I think optimizing this voxelshape code without changing the behavior to be different from vanilla is not feasible. It exposes lots of implementation details (1e-7 margins, </<= mixups, floating point operation order, directionality, sideeffects of shape "simplification") in a few corner cases. I think it would be best to avoid using VoxelShapes in your use case. For vanilla village generation there might be something that can be optimized, if those corner cases are not hit.