1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-01-21 06:26:55 +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:
SquidDev 2018-11-21 16:46:42 +00:00
parent f9c91f288f
commit 93cb6547bd
4 changed files with 77 additions and 51 deletions

View File

@ -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'

View File

@ -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 )

View File

@ -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,15 +69,9 @@ 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;
}
} );
state.debug = new DebugHandler( state )
{ {
private int count = 0; private int count = 0;
private boolean hasSoftAbort; private boolean hasSoftAbort;
@ -76,7 +82,7 @@ public class CobaltLuaMachine implements ILuaMachine
int count = ++this.count; int count = ++this.count;
if( count > 100000 ) if( count > 100000 )
{ {
if( m_hardAbortMessage != null ) LuaThread.yield( state, NONE ); if( m_hardAbortMessage != null ) LuaThread.yield( m_state, NONE );
this.count = 0; this.count = 0;
} }
else else
@ -90,19 +96,22 @@ public class CobaltLuaMachine implements ILuaMachine
@Override @Override
public void poll() throws LuaError public void poll() throws LuaError
{ {
if( m_hardAbortMessage != null ) LuaThread.yield( state, NONE ); if( m_hardAbortMessage != null ) LuaThread.yield( m_state, NONE );
handleSoftAbort(); handleSoftAbort();
} }
private void handleSoftAbort() throws LuaError { private void handleSoftAbort() throws LuaError
{
// If the soft abort has been cleared then we can reset our flags and continue. // If the soft abort has been cleared then we can reset our flags and continue.
String message = m_softAbortMessage; String message = m_softAbortMessage;
if (message == null) { if( message == null )
{
hasSoftAbort = false; hasSoftAbort = false;
return; return;
} }
if (hasSoftAbort && m_hardAbortMessage == null) { if( hasSoftAbort && m_hardAbortMessage == null )
{
// If we have fired our soft abort, but we haven't been hard aborted then everything is OK. // If we have fired our soft abort, but we haven't been hard aborted then everything is OK.
return; return;
} }
@ -110,7 +119,21 @@ public class CobaltLuaMachine implements ILuaMachine
hasSoftAbort = true; hasSoftAbort = true;
throw new LuaError( message ); throw new LuaError( message );
} }
}; } )
.coroutineFactory( command -> {
Tracking.addValue( m_computer, TrackingField.COROUTINES_CREATED, 1 );
coroutines.execute( () -> {
try
{
command.run();
}
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 );

View File

@ -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;