我使用 Java Flight Recorder 查看执行LogCommandTest
.
仔细观察,当前的应用程序逻辑重新初始化一个新CommandLine
模型,Log
每次调用LogCommand
. 这是确保每次调用都重置所有值的一种方法,但是当命令被大量调用时,它会变得很昂贵。幸运的是,这不是唯一的方法。
我建议您创建CommandLine
一次对象,然后将其重用于所有后续调用。Picocli 旨在以这种方式使用:在解析新的用户输入之前,picocli 会将选项和参数重置为其默认值。
下面的补丁实现了这一点。我专注于 OP,LogCommand
因为这就是 OP 的意义所在,但您可能希望对其他经常调用的性能敏感命令应用类似的更改。
我测试了以下内容,发现LogCommandTest.testPerformance
我的机器上的测试时间从 5 秒缩短到了 0.5 秒。中的其他测试LogCommandTest
仍然通过。
建议的补丁:
Index: jsoar-core/src/main/java/org/jsoar/kernel/commands/LogCommand.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- jsoar-core/src/main/java/org/jsoar/kernel/commands/LogCommand.java (revision 576ae0a1420177bad69d2f9e2e0d405c74f87ab0)
+++ jsoar-core/src/main/java/org/jsoar/kernel/commands/LogCommand.java (date 1577052510919)
@@ -23,6 +23,7 @@
import org.jsoar.util.commands.SoarCommandContext;
import org.jsoar.util.commands.SoarCommandInterpreter;
+import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.HelpCommand;
import picocli.CommandLine.Model.CommandSpec;
@@ -39,17 +40,22 @@
{
private final Agent agent;
private SoarCommandInterpreter interpreter;
+ private Log log;
+ private CommandLine logCommand;
public LogCommand(Agent agent, SoarCommandInterpreter interpreter)
{
this.agent = agent;
this.interpreter = interpreter;
+ this.log = new Log(agent, interpreter, null);
+ this.logCommand = new CommandLine(log);
}
@Override
public String execute(SoarCommandContext context, String[] args) throws SoarException
{
- Utils.parseAndRun(agent, new Log(agent, interpreter, context), args);
+ this.log.context = context;
+ Utils.parseAndRun(agent, logCommand, args);
return "";
}
@@ -57,7 +63,7 @@
@Override
public Object getCommand()
{
- return new Log(agent,interpreter,null);
+ return logCommand;
}
@Command(name="log", description="Adjusts logging settings",
@@ -67,7 +73,7 @@
private final Agent agent;
private final LogManager logManager;
private final SoarCommandInterpreter interpreter;
- private final SoarCommandContext context;
+ private SoarCommandContext context;
private static String sourceLocationSeparator = ".";
@Spec
Index: jsoar-core/src/main/java/org/jsoar/kernel/commands/Utils.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- jsoar-core/src/main/java/org/jsoar/kernel/commands/Utils.java (revision 576ae0a1420177bad69d2f9e2e0d405c74f87ab0)
+++ jsoar-core/src/main/java/org/jsoar/kernel/commands/Utils.java (date 1577052217242)
@@ -41,10 +41,25 @@
parseAndRun(command, args, ps);
}
-
+
+ /**
+ * Executes the specified command and returns the result.
+ * A command may be a user object or a pre-initialized {@code picocli.CommandLine} object.
+ * For performance-sensitive commands that are invoked often,
+ * it is recommended to pass a pre-initialized CommandLine object instead of the user object.
+ *
+ * @param command the command to execute; this may be a user object or a pre-initialized {@code picocli.CommandLine} object
+ * @param args the command line arguments (the first arg will be removed from this list)
+ * @param ps the PrintStream to print any command output to
+ * @return the command result
+ * @throws SoarException if the user input was invalid or if a runtime exception occurred
+ * while executing the command business logic
+ */
public static List<Object> parseAndRun(Object command, String[] args, PrintStream ps) throws SoarException {
- CommandLine commandLine = new CommandLine(command);
+ CommandLine commandLine = command instanceof CommandLine
+ ? (CommandLine) command
+ : new CommandLine(command);
// The "debug time" command takes a command as a parameter, which can contain options
// In order to inform picocli that the options are part of the command parameter