From e1eb40c129c06938ea1e71572c212d2d28d36fb8 Mon Sep 17 00:00:00 2001 From: Glavo Date: Fri, 25 Nov 2022 17:16:23 +0800 Subject: [PATCH] Optimization HMCLProcessListener::onLog (#1867) --- .../jackhuang/hmcl/game/LauncherHelper.java | 37 +++++++++++++------ .../jackhuang/hmcl/ui/GameCrashWindow.java | 3 +- .../java/org/jackhuang/hmcl/ui/LogWindow.java | 5 +-- .../hmcl/launch/DefaultLauncher.java | 7 ++-- .../hmcl/launch/ProcessListener.java | 3 +- .../java/org/jackhuang/hmcl/util/Lang.java | 7 ++++ 6 files changed, 41 insertions(+), 21 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java index c75949e30..a5659a7c5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -685,7 +685,7 @@ public final class LauncherHelper { * Guarantee that one [JavaProcess], one [HMCLProcessListener]. * Because every time we launched a game, we generates a new [HMCLProcessListener] */ - class HMCLProcessListener implements ProcessListener { + private final class HMCLProcessListener implements ProcessListener { private final HMCLGameRepository repository; private final Version version; @@ -694,9 +694,11 @@ public final class LauncherHelper { private boolean lwjgl; private LogWindow logWindow; private final boolean detectWindow; - private final ArrayDeque> logs; + private final ArrayDeque logs; + private final ArrayDeque levels; private final CountDownLatch logWindowLatch = new CountDownLatch(1); private final CountDownLatch launchingLatch; + private final String forbiddenAccessToken; public HMCLProcessListener(HMCLGameRepository repository, Version version, AuthInfo authInfo, LaunchOptions launchOptions, CountDownLatch launchingLatch, boolean detectWindow) { this.repository = repository; @@ -704,8 +706,11 @@ public final class LauncherHelper { this.launchOptions = launchOptions; this.launchingLatch = launchingLatch; this.detectWindow = detectWindow; + this.forbiddenAccessToken = authInfo != null ? authInfo.getAccessToken() : null; - this.logs = new ArrayDeque<>(config().getLogLines() + 1); + final int numLogs = config().getLogLines() + 1; + this.logs = new ArrayDeque<>(numLogs); + this.levels = new ArrayDeque<>(numLogs); } @Override @@ -764,17 +769,24 @@ public final class LauncherHelper { } @Override - public synchronized void onLog(String log, Log4jLevel level) { - String filteredLog = Logging.filterForbiddenToken(log); + public void onLog(String log, boolean isErrorStream) { + String filteredLog = forbiddenAccessToken == null ? log : log.replace(forbiddenAccessToken, ""); - if (level.lessOrEqual(Log4jLevel.ERROR)) + if (isErrorStream) System.err.println(filteredLog); else System.out.println(filteredLog); - logs.add(pair(filteredLog, level)); - if (logs.size() > config().getLogLines()) - logs.removeFirst(); + Log4jLevel level = isErrorStream ? Log4jLevel.ERROR : (showLogs ? Log4jLevel.guessLevel(filteredLog) : null); + + synchronized (this) { + logs.add(filteredLog); + levels.add(level != null ? level : Optional.empty()); // Use 'Optional.empty()' as hole + if (logs.size() > config().getLogLines()) { + logs.removeFirst(); + levels.removeFirst(); + } + } if (showLogs) { try { @@ -787,7 +799,7 @@ public final class LauncherHelper { Platform.runLater(() -> logWindow.logLine(filteredLog, level)); } - if (!lwjgl && (filteredLog.toLowerCase().contains("lwjgl version") || filteredLog.toLowerCase().contains("lwjgl openal") || !detectWindow)) { + if (!lwjgl && (!detectWindow || filteredLog.toLowerCase().contains("lwjgl version") || filteredLog.toLowerCase().contains("lwjgl openal"))) { lwjgl = true; finishLaunch(); } @@ -804,8 +816,11 @@ public final class LauncherHelper { if (!lwjgl) finishLaunch(); if (exitType != ExitType.NORMAL) { + ArrayList> pairs = new ArrayList<>(logs.size()); + Lang.forEachZipped(logs, levels, + (log, l) -> pairs.add(pair(log, l instanceof Log4jLevel ? ((Log4jLevel) l) : Log4jLevel.guessLevel(log)))); repository.markVersionLaunchedAbnormally(version.getId()); - Platform.runLater(() -> new GameCrashWindow(process, exitType, repository, version, launchOptions, logs).show()); + Platform.runLater(() -> new GameCrashWindow(process, exitType, repository, version, launchOptions, pairs).show()); } checkExit(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java index ac7c93830..1d82f24d5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java @@ -42,6 +42,7 @@ import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.ui.construct.TwoLineListItem; import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.Log4jLevel; +import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.Pair; import org.jackhuang.hmcl.util.platform.Architecture; import org.jackhuang.hmcl.util.platform.CommandBuilder; @@ -222,7 +223,7 @@ public class GameCrashWindow extends Stage { private void showLogWindow() { LogWindow logWindow = new LogWindow(); - logWindow.logLine("Command: " + new CommandBuilder().addAll(managedProcess.getCommands()).toString(), Log4jLevel.INFO); + logWindow.logLine(Logging.filterForbiddenToken("Command: " + new CommandBuilder().addAll(managedProcess.getCommands())), Log4jLevel.INFO); if (managedProcess.getClasspath() != null) logWindow.logLine("ClassPath: " + managedProcess.getClasspath(), Log4jLevel.INFO); for (Map.Entry entry : logs) logWindow.logLine(entry.getKey(), entry.getValue()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java index 10f3f34ac..3fbd60489 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java @@ -37,7 +37,6 @@ import javafx.stage.Stage; import org.apache.commons.lang3.mutable.MutableObject; import org.jackhuang.hmcl.game.LauncherHelper; import org.jackhuang.hmcl.util.Log4jLevel; -import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.platform.OperatingSystem; import java.io.IOException; @@ -95,8 +94,8 @@ public final class LogWindow extends Stage { levelShownMap.values().forEach(property -> property.addListener((a, b, newValue) -> shakeLogs())); } - public void logLine(String line, Log4jLevel level) { - Log log = new Log(Logging.filterForbiddenToken(parseEscapeSequence(line)), level); + public void logLine(String filteredLine, Log4jLevel level) { + Log log = new Log(parseEscapeSequence(filteredLine), level); logs.add(log); if (levelShownMap.get(level).get()) impl.listView.getItems().add(log); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java index ce679dbb6..3651fcac5 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java @@ -21,7 +21,6 @@ import org.jackhuang.hmcl.auth.AuthInfo; import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.game.*; import org.jackhuang.hmcl.util.Lang; -import org.jackhuang.hmcl.util.Log4jLevel; import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.gson.UUIDTypeAdapter; import org.jackhuang.hmcl.util.io.FileUtils; @@ -646,15 +645,15 @@ public class DefaultLauncher extends Launcher { throw new ExecutionPolicyLimitException(); } - private void startMonitors(ManagedProcess managedProcess, ProcessListener processListener, Charset encoding, boolean isDaemon) { + private static void startMonitors(ManagedProcess managedProcess, ProcessListener processListener, Charset encoding, boolean isDaemon) { processListener.setProcess(managedProcess); Thread stdout = Lang.thread(new StreamPump(managedProcess.getProcess().getInputStream(), it -> { - processListener.onLog(it, Optional.ofNullable(Log4jLevel.guessLevel(it)).orElse(Log4jLevel.INFO)); + processListener.onLog(it, false); managedProcess.addLine(it); }, encoding), "stdout-pump", isDaemon); managedProcess.addRelatedThread(stdout); Thread stderr = Lang.thread(new StreamPump(managedProcess.getProcess().getErrorStream(), it -> { - processListener.onLog(it, Log4jLevel.ERROR); + processListener.onLog(it, true); managedProcess.addLine(it); }, encoding), "stderr-pump", isDaemon); managedProcess.addRelatedThread(stderr); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/ProcessListener.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/ProcessListener.java index 15d71c3a2..2b3605fa7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/ProcessListener.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/ProcessListener.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.launch; -import org.jackhuang.hmcl.util.Log4jLevel; import org.jackhuang.hmcl.util.platform.ManagedProcess; /** @@ -40,7 +39,7 @@ public interface ProcessListener { * * @param log the log */ - void onLog(String log, Log4jLevel level); + void onLog(String log, boolean isErrorStream); /** * Called when the game process stops. diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java index d7083af52..183d3f5c0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Lang.java @@ -366,6 +366,13 @@ public final class Lang { return () -> iterator; } + public static void forEachZipped(Iterable i1, Iterable i2, BiConsumer action) { + Iterator it1 = i1.iterator(); + Iterator it2 = i2.iterator(); + while (it1.hasNext() && it2.hasNext()) + action.accept(it1.next(), it2.next()); + } + private static Timer timer; public static synchronized Timer getTimer() {