mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-31 05:33:00 +00:00 
			
		
		
		
	Improvements for coroutine creation
- Keep track of the number of created and destroyed coroutines for each computer. - Run coroutines with a thread pool executor, which will keep stale threads around for 60 seconds. This substantially reduces the pressure from short-lived coroutines. - Update to the latest Cobalt version.
This commit is contained in:
		| @@ -66,7 +66,7 @@ dependencies { | |||||||
|  |  | ||||||
|     runtime "mezz.jei:jei_1.12.2:4.8.5.159" |     runtime "mezz.jei:jei_1.12.2:4.8.5.159" | ||||||
|  |  | ||||||
|     shade 'org.squiddev:Cobalt:0.3.2' |     shade 'org.squiddev:Cobalt:0.4.0' | ||||||
|  |  | ||||||
|     testCompile 'junit:junit:4.11' |     testCompile 'junit:junit:4.11' | ||||||
|  |  | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ public final class HTTPExecutor | |||||||
|     public static final ListeningExecutorService EXECUTOR = MoreExecutors.listeningDecorator( new ThreadPoolExecutor( |     public static final ListeningExecutorService EXECUTOR = MoreExecutors.listeningDecorator( new ThreadPoolExecutor( | ||||||
|         4, Integer.MAX_VALUE, |         4, Integer.MAX_VALUE, | ||||||
|         60L, TimeUnit.SECONDS, |         60L, TimeUnit.SECONDS, | ||||||
|         new SynchronousQueue<Runnable>(), |         new SynchronousQueue<>(), | ||||||
|         new ThreadFactoryBuilder() |         new ThreadFactoryBuilder() | ||||||
|             .setDaemon( true ) |             .setDaemon( true ) | ||||||
|             .setPriority( Thread.MIN_PRIORITY + (Thread.NORM_PRIORITY - Thread.MIN_PRIORITY) / 2 ) |             .setPriority( Thread.MIN_PRIORITY + (Thread.NORM_PRIORITY - Thread.MIN_PRIORITY) / 2 ) | ||||||
|   | |||||||
| @@ -6,15 +6,14 @@ | |||||||
|  |  | ||||||
| package dan200.computercraft.core.lua; | package dan200.computercraft.core.lua; | ||||||
|  |  | ||||||
|  | import com.google.common.util.concurrent.ThreadFactoryBuilder; | ||||||
| import dan200.computercraft.ComputerCraft; | import dan200.computercraft.ComputerCraft; | ||||||
| import dan200.computercraft.api.lua.ILuaContext; | import dan200.computercraft.api.lua.*; | ||||||
| import dan200.computercraft.api.lua.ILuaObject; |  | ||||||
| import dan200.computercraft.api.lua.ILuaTask; |  | ||||||
| import dan200.computercraft.api.lua.LuaException; |  | ||||||
| import dan200.computercraft.api.lua.ILuaAPI; |  | ||||||
| import dan200.computercraft.core.computer.Computer; | import dan200.computercraft.core.computer.Computer; | ||||||
| import dan200.computercraft.core.computer.ITask; | import dan200.computercraft.core.computer.ITask; | ||||||
| import dan200.computercraft.core.computer.MainThread; | import dan200.computercraft.core.computer.MainThread; | ||||||
|  | import dan200.computercraft.core.tracking.Tracking; | ||||||
|  | import dan200.computercraft.core.tracking.TrackingField; | ||||||
| import org.squiddev.cobalt.*; | import org.squiddev.cobalt.*; | ||||||
| import org.squiddev.cobalt.compiler.CompileException; | import org.squiddev.cobalt.compiler.CompileException; | ||||||
| import org.squiddev.cobalt.compiler.LoadState; | import org.squiddev.cobalt.compiler.LoadState; | ||||||
| @@ -25,7 +24,7 @@ import org.squiddev.cobalt.function.LibFunction; | |||||||
| import org.squiddev.cobalt.function.LuaFunction; | import org.squiddev.cobalt.function.LuaFunction; | ||||||
| import org.squiddev.cobalt.function.VarArgFunction; | import org.squiddev.cobalt.function.VarArgFunction; | ||||||
| import org.squiddev.cobalt.lib.*; | import org.squiddev.cobalt.lib.*; | ||||||
| import org.squiddev.cobalt.lib.platform.AbstractResourceManipulator; | import org.squiddev.cobalt.lib.platform.VoidResourceManipulator; | ||||||
|  |  | ||||||
| import javax.annotation.Nonnull; | import javax.annotation.Nonnull; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| @@ -35,6 +34,9 @@ import java.util.Arrays; | |||||||
| import java.util.HashMap; | import java.util.HashMap; | ||||||
| import java.util.IdentityHashMap; | import java.util.IdentityHashMap; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
|  | import java.util.concurrent.SynchronousQueue; | ||||||
|  | import java.util.concurrent.ThreadPoolExecutor; | ||||||
|  | import java.util.concurrent.TimeUnit; | ||||||
|  |  | ||||||
| import static org.squiddev.cobalt.Constants.NONE; | import static org.squiddev.cobalt.Constants.NONE; | ||||||
| import static org.squiddev.cobalt.ValueFactory.valueOf; | import static org.squiddev.cobalt.ValueFactory.valueOf; | ||||||
| @@ -42,6 +44,16 @@ import static org.squiddev.cobalt.ValueFactory.varargsOf; | |||||||
|  |  | ||||||
| public class CobaltLuaMachine implements ILuaMachine | public class CobaltLuaMachine implements ILuaMachine | ||||||
| { | { | ||||||
|  |     private static final ThreadPoolExecutor coroutines = new ThreadPoolExecutor( | ||||||
|  |         0, Integer.MAX_VALUE, | ||||||
|  |         60L, TimeUnit.SECONDS, | ||||||
|  |         new SynchronousQueue<>(), | ||||||
|  |         new ThreadFactoryBuilder() | ||||||
|  |             .setDaemon( true ) | ||||||
|  |             .setNameFormat( "ComputerCraft-Coroutine-%d" ) | ||||||
|  |             .build() | ||||||
|  |     ); | ||||||
|  |  | ||||||
|     private final Computer m_computer; |     private final Computer m_computer; | ||||||
|  |  | ||||||
|     private final LuaState m_state; |     private final LuaState m_state; | ||||||
| @@ -57,60 +69,71 @@ public class CobaltLuaMachine implements ILuaMachine | |||||||
|         m_computer = computer; |         m_computer = computer; | ||||||
|  |  | ||||||
|         // Create an environment to run in |         // Create an environment to run in | ||||||
|         final LuaState state = this.m_state = new LuaState( new AbstractResourceManipulator() |         LuaState state = this.m_state = LuaState.builder() | ||||||
|         { |             .resourceManipulator( new VoidResourceManipulator() ) | ||||||
|             @Override |             .debug( new DebugHandler() | ||||||
|             public InputStream findResource( String filename ) |  | ||||||
|             { |             { | ||||||
|                 return null; |                 private int count = 0; | ||||||
|             } |                 private boolean hasSoftAbort; | ||||||
|         } ); |  | ||||||
|         state.debug = new DebugHandler( state ) |  | ||||||
|         { |  | ||||||
|             private int count = 0; |  | ||||||
|             private boolean hasSoftAbort; |  | ||||||
|  |  | ||||||
|             @Override |                 @Override | ||||||
|             public void onInstruction( DebugState ds, DebugFrame di, int pc, Varargs extras, int top ) throws LuaError |                 public void onInstruction( DebugState ds, DebugFrame di, int pc, Varargs extras, int top ) throws LuaError | ||||||
|             { |  | ||||||
|                 int count = ++this.count; |  | ||||||
|                 if( count > 100000 ) |  | ||||||
|                 { |                 { | ||||||
|                     if( m_hardAbortMessage != null ) LuaThread.yield( state, NONE ); |                     int count = ++this.count; | ||||||
|                     this.count = 0; |                     if( count > 100000 ) | ||||||
|  |                     { | ||||||
|  |                         if( m_hardAbortMessage != null ) LuaThread.yield( m_state, NONE ); | ||||||
|  |                         this.count = 0; | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         handleSoftAbort(); | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     super.onInstruction( ds, di, pc, extras, top ); | ||||||
|                 } |                 } | ||||||
|                 else |  | ||||||
|  |                 @Override | ||||||
|  |                 public void poll() throws LuaError | ||||||
|                 { |                 { | ||||||
|  |                     if( m_hardAbortMessage != null ) LuaThread.yield( m_state, NONE ); | ||||||
|                     handleSoftAbort(); |                     handleSoftAbort(); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 super.onInstruction( ds, di, pc, extras, top ); |                 private void handleSoftAbort() throws LuaError | ||||||
|             } |                 { | ||||||
|  |                     // If the soft abort has been cleared then we can reset our flags and continue. | ||||||
|  |                     String message = m_softAbortMessage; | ||||||
|  |                     if( message == null ) | ||||||
|  |                     { | ||||||
|  |                         hasSoftAbort = false; | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  |  | ||||||
|             @Override |                     if( hasSoftAbort && m_hardAbortMessage == null ) | ||||||
|             public void poll() throws LuaError |                     { | ||||||
|             { |                         // If we have fired our soft abort, but we haven't been hard aborted then everything is OK. | ||||||
|                 if( m_hardAbortMessage != null ) LuaThread.yield( state, NONE ); |                         return; | ||||||
|                 handleSoftAbort(); |                     } | ||||||
|             } |  | ||||||
|  |  | ||||||
|             private void handleSoftAbort() throws LuaError { |                     hasSoftAbort = true; | ||||||
|                 // If the soft abort has been cleared then we can reset our flags and continue. |                     throw new LuaError( message ); | ||||||
|                 String message = m_softAbortMessage; |  | ||||||
|                 if (message == null) { |  | ||||||
|                     hasSoftAbort = false; |  | ||||||
|                     return; |  | ||||||
|                 } |                 } | ||||||
|  |             } ) | ||||||
|                 if (hasSoftAbort && m_hardAbortMessage == null) { |             .coroutineFactory( command -> { | ||||||
|                     // If we have fired our soft abort, but we haven't been hard aborted then everything is OK. |                 Tracking.addValue( m_computer, TrackingField.COROUTINES_CREATED, 1 ); | ||||||
|                     return; |                 coroutines.execute( () -> { | ||||||
|                 } |                     try | ||||||
|  |                     { | ||||||
|                 hasSoftAbort = true; |                         command.run(); | ||||||
|                 throw new LuaError(message); |                     } | ||||||
|             } |                     finally | ||||||
|         }; |                     { | ||||||
|  |                         Tracking.addValue( m_computer, TrackingField.COROUTINES_DISPOSED, 1 ); | ||||||
|  |                     } | ||||||
|  |                 } ); | ||||||
|  |             } ) | ||||||
|  |             .build(); | ||||||
|  |  | ||||||
|         m_globals = new LuaTable(); |         m_globals = new LuaTable(); | ||||||
|         state.setupThread( m_globals ); |         state.setupThread( m_globals ); | ||||||
|   | |||||||
| @@ -28,6 +28,9 @@ public class TrackingField | |||||||
|     public static final TrackingField WEBSOCKET_INCOMING = TrackingField.of( "websocket_incoming", "Websocket incoming", TrackingField::formatBytes ); |     public static final TrackingField WEBSOCKET_INCOMING = TrackingField.of( "websocket_incoming", "Websocket incoming", TrackingField::formatBytes ); | ||||||
|     public static final TrackingField WEBSOCKET_OUTGOING = TrackingField.of( "websocket_outgoing", "Websocket outgoing", TrackingField::formatBytes ); |     public static final TrackingField WEBSOCKET_OUTGOING = TrackingField.of( "websocket_outgoing", "Websocket outgoing", TrackingField::formatBytes ); | ||||||
|  |  | ||||||
|  |     public static final TrackingField COROUTINES_CREATED = TrackingField.of( "coroutines_created", "Coroutines created", x -> String.format( "%4d", x ) ); | ||||||
|  |     public static final TrackingField COROUTINES_DISPOSED = TrackingField.of( "coroutines_dead", "Coroutines disposed", x -> String.format( "%4d", x ) ); | ||||||
|  |  | ||||||
|     private final String id; |     private final String id; | ||||||
|     private final String displayName; |     private final String displayName; | ||||||
|     private final LongFunction<String> format; |     private final LongFunction<String> format; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 SquidDev
					SquidDev