mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-01-15 03:35:42 +00:00
Use a queue rather than a set in TickScheduler
We now track whether a tile is enqueued or not via an atomic boolean on the block entity itself, rather than using a hash set. This is significantly faster (>10x). This is mostly intended for monitors, as they're the only peripheral likely to call TickScheduler.schedule lots of times (rather than modems, which just invoke it when opening/closing a channel[^1])[^2]. This change is enough to allow me to update 120 monitors each tick without any major tearing. [^1]: GPS does do this on each gps.locate call, so it will help there, but modems are typically limited by other computers sending messages, not peripheral calls themselves. [^2]: Note that montitors implement their own change tracking, so still only call this once per tick. But it's enough to introduce some latency!
This commit is contained in:
parent
1fd57a874f
commit
4411756b06
@ -19,9 +19,17 @@ import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public abstract class TileGeneric extends TileEntity
|
||||
{
|
||||
/**
|
||||
* Is this block enqueued to be updated next tick? This should only be read/written by the tick scheduler.
|
||||
*
|
||||
* @see dan200.computercraft.shared.util.TickScheduler
|
||||
*/
|
||||
public final AtomicBoolean scheduled = new AtomicBoolean();
|
||||
|
||||
public TileGeneric( TileEntityType<? extends TileGeneric> type )
|
||||
{
|
||||
super( type );
|
||||
|
@ -5,10 +5,8 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.util;
|
||||
|
||||
import com.google.common.collect.MapMaker;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.ITickList;
|
||||
import net.minecraft.world.World;
|
||||
@ -16,9 +14,8 @@ import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
|
||||
/**
|
||||
* A thread-safe version of {@link ITickList#scheduleTick(BlockPos, Object, int)}.
|
||||
@ -32,16 +29,12 @@ public final class TickScheduler
|
||||
{
|
||||
}
|
||||
|
||||
private static final Set<TileEntity> toTick = Collections.newSetFromMap(
|
||||
new MapMaker()
|
||||
.weakKeys()
|
||||
.makeMap()
|
||||
);
|
||||
private static final Queue<TileGeneric> toTick = new ConcurrentLinkedDeque<>();
|
||||
|
||||
public static void schedule( TileGeneric tile )
|
||||
{
|
||||
World world = tile.getLevel();
|
||||
if( world != null && !world.isClientSide ) toTick.add( tile );
|
||||
if( world != null && !world.isClientSide && !tile.scheduled.getAndSet( true ) ) toTick.add( tile );
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@ -49,11 +42,11 @@ public final class TickScheduler
|
||||
{
|
||||
if( event.phase != TickEvent.Phase.START ) return;
|
||||
|
||||
Iterator<TileEntity> iterator = toTick.iterator();
|
||||
while( iterator.hasNext() )
|
||||
TileGeneric tile;
|
||||
while( (tile = toTick.poll()) != null )
|
||||
{
|
||||
TileEntity tile = iterator.next();
|
||||
iterator.remove();
|
||||
tile.scheduled.set( false );
|
||||
if( tile.isRemoved() ) continue;
|
||||
|
||||
World world = tile.getLevel();
|
||||
BlockPos pos = tile.getBlockPos();
|
||||
|
Loading…
Reference in New Issue
Block a user