Asynchronously log messages to the Console window (#395)
* Logging: Asynchronously log messages to the Console window Writing to the Console blocks until the write completes. This has the potential to block any code path that logs to the application logger. By queuing up log messages in an asynchronous queue and returning without blocking, we can speed up code paths that heavily log to the console (for example stubbed services like ServiceHid). From testing this results in a roughly 8% time decrease between Ryujinx startup and the splash screen in Super Mario Odyssey on my system - 00:03:19.591 down to 00:03:04.354. Depending on your system, YMMV. * Logging: Resolve code styling issues
This commit is contained in:
parent
675f3f6f81
commit
76a3172f17
2 changed files with 40 additions and 3 deletions
|
@ -1,5 +1,6 @@
|
||||||
using Ryujinx.HLE.Logging;
|
using Ryujinx.HLE.Logging;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
|
@ -7,6 +8,10 @@ namespace Ryujinx
|
||||||
{
|
{
|
||||||
static class ConsoleLog
|
static class ConsoleLog
|
||||||
{
|
{
|
||||||
|
private static Thread MessageThread;
|
||||||
|
|
||||||
|
private static BlockingCollection<LogEventArgs> MessageQueue;
|
||||||
|
|
||||||
private static Dictionary<LogLevel, ConsoleColor> LogColors;
|
private static Dictionary<LogLevel, ConsoleColor> LogColors;
|
||||||
|
|
||||||
private static object ConsoleLock;
|
private static object ConsoleLock;
|
||||||
|
@ -21,10 +26,34 @@ namespace Ryujinx
|
||||||
{ LogLevel.Error, ConsoleColor.Red }
|
{ LogLevel.Error, ConsoleColor.Red }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MessageQueue = new BlockingCollection<LogEventArgs>();
|
||||||
|
|
||||||
ConsoleLock = new object();
|
ConsoleLock = new object();
|
||||||
|
|
||||||
|
MessageThread = new Thread(() =>
|
||||||
|
{
|
||||||
|
while (!MessageQueue.IsCompleted)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PrintLog(MessageQueue.Take());
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
// IOE means that Take() was called on a completed collection.
|
||||||
|
// Some other thread can call CompleteAdding after we pass the
|
||||||
|
// IsCompleted check but before we call Take.
|
||||||
|
// We can simply catch the exception since the loop will break
|
||||||
|
// on the next iteration.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
MessageThread.IsBackground = true;
|
||||||
|
MessageThread.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PrintLog(object sender, LogEventArgs e)
|
private static void PrintLog(LogEventArgs e)
|
||||||
{
|
{
|
||||||
string FormattedTime = e.Time.ToString(@"hh\:mm\:ss\.fff");
|
string FormattedTime = e.Time.ToString(@"hh\:mm\:ss\.fff");
|
||||||
|
|
||||||
|
@ -47,5 +76,13 @@ namespace Ryujinx
|
||||||
Console.WriteLine(Message);
|
Console.WriteLine(Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Log(object sender, LogEventArgs e)
|
||||||
|
{
|
||||||
|
if (!MessageQueue.IsAddingCompleted)
|
||||||
|
{
|
||||||
|
MessageQueue.Add(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@ namespace Ryujinx
|
||||||
|
|
||||||
Config.Read(Device);
|
Config.Read(Device);
|
||||||
|
|
||||||
Device.Log.Updated += ConsoleLog.PrintLog;
|
Device.Log.Updated += ConsoleLog.Log;
|
||||||
|
|
||||||
if (args.Length == 1)
|
if (args.Length == 1)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue