mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-30 21:23:00 +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:
		| @@ -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(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jonathan Coates
					Jonathan Coates