mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-01-28 09:54:47 +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 net.minecraftforge.common.util.Constants;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
public abstract class TileGeneric extends TileEntity
|
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 )
|
public TileGeneric( TileEntityType<? extends TileGeneric> type )
|
||||||
{
|
{
|
||||||
super( type );
|
super( type );
|
||||||
|
@ -5,10 +5,8 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.shared.util;
|
package dan200.computercraft.shared.util;
|
||||||
|
|
||||||
import com.google.common.collect.MapMaker;
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import dan200.computercraft.shared.common.TileGeneric;
|
import dan200.computercraft.shared.common.TileGeneric;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.ITickList;
|
import net.minecraft.world.ITickList;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
@ -16,9 +14,8 @@ import net.minecraftforge.event.TickEvent;
|
|||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Queue;
|
||||||
import java.util.Iterator;
|
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A thread-safe version of {@link ITickList#scheduleTick(BlockPos, Object, int)}.
|
* 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(
|
private static final Queue<TileGeneric> toTick = new ConcurrentLinkedDeque<>();
|
||||||
new MapMaker()
|
|
||||||
.weakKeys()
|
|
||||||
.makeMap()
|
|
||||||
);
|
|
||||||
|
|
||||||
public static void schedule( TileGeneric tile )
|
public static void schedule( TileGeneric tile )
|
||||||
{
|
{
|
||||||
World world = tile.getLevel();
|
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
|
@SubscribeEvent
|
||||||
@ -49,11 +42,11 @@ public final class TickScheduler
|
|||||||
{
|
{
|
||||||
if( event.phase != TickEvent.Phase.START ) return;
|
if( event.phase != TickEvent.Phase.START ) return;
|
||||||
|
|
||||||
Iterator<TileEntity> iterator = toTick.iterator();
|
TileGeneric tile;
|
||||||
while( iterator.hasNext() )
|
while( (tile = toTick.poll()) != null )
|
||||||
{
|
{
|
||||||
TileEntity tile = iterator.next();
|
tile.scheduled.set( false );
|
||||||
iterator.remove();
|
if( tile.isRemoved() ) continue;
|
||||||
|
|
||||||
World world = tile.getLevel();
|
World world = tile.getLevel();
|
||||||
BlockPos pos = tile.getBlockPos();
|
BlockPos pos = tile.getBlockPos();
|
||||||
|
Loading…
Reference in New Issue
Block a user