11-09-2012, 07:05 AM
The current implementation of physics simulators is less than satisfactory. I tried to make water flow upon chunk load (so that waterfalls work and undersea caverns fill with water), and the architecture simply overwhelms the server. One tick takes several seconds due to the simulators.
I've traced the main problem to be that the simulators look up each and every block through cWorld::GetBlock(), simply because they have to. That function has to lock the chunkmap, locate the correct chunk, ask it for block parameters... Just too much work per single block, considering that they may be thousands of blocks needing to update every tick.
Here's some profiling info from my tests:
Notice that the tick durations are totally unpredictable and completely degrade the server performance (>10s per some ticks!!!)
So how to improve this? I think the simulator should be called for each chunk individually, with the direct access to chunk's block data. That way, it won't have to do the lookups, it could even inspect (most) block neighbors without lookups, and it could process all blocks inside one chunk within one chunkmap-lock operation.
However, the current scheme of storing blocks for waking up would need to be somehow rewritten, too. Haven't gotten so far yet, will post updates as I make my mind up about it
I've traced the main problem to be that the simulators look up each and every block through cWorld::GetBlock(), simply because they have to. That function has to lock the chunkmap, locate the correct chunk, ask it for block parameters... Just too much work per single block, considering that they may be thousands of blocks needing to update every tick.
Here's some profiling info from my tests:
Code:
cRedstoneSimulator::Simulate: 65089 torches, 0 repeaters, 56 blocks took 15072 ticks (15.07 sec)
cDelayedFluidSimulator::Simulate: 109 blocks took 63 ticks (0.06 sec)
cRedstoneSimulator::Simulate: 580 torches, 0 repeaters, 101 blocks took 31 ticks (0.03 sec)
cDelayedFluidSimulator::Simulate: 2911 blocks took 1781 ticks (1.78 sec)
cRedstoneSimulator::Simulate: 873 torches, 0 repeaters, 2301 blocks took 531 ticks (0.53 sec)
cDelayedFluidSimulator::Simulate: 1085 blocks took 172 ticks (0.17 sec)
cRedstoneSimulator::Simulate: 19261 torches, 0 repeaters, 10835 blocks took 7607 ticks (7.61 sec)
cDelayedFluidSimulator::Simulate: 69 blocks took 78 ticks (0.08 sec)
cRedstoneSimulator::Simulate: 91065 torches, 0 repeaters, 215 blocks took 2078 ticks (2.08 sec)
Generating chunk [16, 0, -26]
cDelayedFluidSimulator::Simulate: 201 blocks took 156 ticks (0.16 sec)
cRedstoneSimulator::Simulate: 2156 torches, 0 repeaters, 93 blocks took 1671 ticks (1.67 sec)
cChunkMap::WakeUpFluidSimulators took 16 ticks (0.02 sec)
cDelayedFluidSimulator::Simulate: 3381 blocks took 1843 ticks (1.84 sec)
cRedstoneSimulator::Simulate: 757 torches, 0 repeaters, 2163 blocks took 547 ticks (0.55 sec)
cDelayedFluidSimulator::Simulate: 1638 blocks took 344 ticks (0.34 sec)
cRedstoneSimulator::Simulate: 17328 torches, 0 repeaters, 10348 blocks took 2890 ticks (2.89 sec)
cDelayedFluidSimulator::Simulate: 172 blocks took 62 ticks (0.06 sec)
cRedstoneSimulator::Simulate: 84823 torches, 0 repeaters, 643 blocks took 1968 ticks (1.97 sec)
cDelayedFluidSimulator::Simulate: 187 blocks took 94 ticks (0.09 sec)
cRedstoneSimulator::Simulate: 5927 torches, 0 repeaters, 113 blocks took 156 ticks (0.16 sec)
cDelayedFluidSimulator::Simulate: 3136 blocks took 1640 ticks (1.64 sec)
cRedstoneSimulator::Simulate: 955 torches, 0 repeaters, 2080 blocks took 531 ticks (0.53 sec)
cDelayedFluidSimulator::Simulate: 1677 blocks took 344 ticks (0.34 sec)
So how to improve this? I think the simulator should be called for each chunk individually, with the direct access to chunk's block data. That way, it won't have to do the lookups, it could even inspect (most) block neighbors without lookups, and it could process all blocks inside one chunk within one chunkmap-lock operation.
However, the current scheme of storing blocks for waking up would need to be somehow rewritten, too. Haven't gotten so far yet, will post updates as I make my mind up about it