mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-01-14 22:50:34 +00:00
Added progress reporter for loading existing translations from PTC
- Refactored existing progress reporter - Added reporting progress when loading existing translations from PTC
This commit is contained in:
parent
5cb83293bc
commit
0f14aa8f1e
1 changed files with 147 additions and 86 deletions
|
@ -66,9 +66,6 @@ namespace ARMeilleure.Translation.PTC
|
||||||
|
|
||||||
internal static PtcState State { get; private set; }
|
internal static PtcState State { get; private set; }
|
||||||
|
|
||||||
// Progress reporting helpers
|
|
||||||
private static volatile int _translateCount;
|
|
||||||
private static volatile int _translateTotalCount;
|
|
||||||
public static event Action<PtcLoadingState, int, int> PtcStateChanged;
|
public static event Action<PtcLoadingState, int, int> PtcStateChanged;
|
||||||
|
|
||||||
static Ptc()
|
static Ptc()
|
||||||
|
@ -527,12 +524,17 @@ namespace ARMeilleure.Translation.PTC
|
||||||
_relocsStream.Seek(0L, SeekOrigin.Begin);
|
_relocsStream.Seek(0L, SeekOrigin.Begin);
|
||||||
_unwindInfosStream.Seek(0L, SeekOrigin.Begin);
|
_unwindInfosStream.Seek(0L, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
// Get total entries to process for progress reporting and for looping.
|
||||||
|
int infoEntriesCount = GetInfosEntriesCount();
|
||||||
|
|
||||||
|
using ProgressReporter progressReporter = ProgressReporter.CreateAndStart(infoEntriesCount, PtcStateChanged);
|
||||||
|
|
||||||
using (BinaryReader infosReader = new(_infosStream, EncodingCache.UTF8NoBOM, true))
|
using (BinaryReader infosReader = new(_infosStream, EncodingCache.UTF8NoBOM, true))
|
||||||
using (BinaryReader codesReader = new(_codesStream, EncodingCache.UTF8NoBOM, true))
|
using (BinaryReader codesReader = new(_codesStream, EncodingCache.UTF8NoBOM, true))
|
||||||
using (BinaryReader relocsReader = new(_relocsStream, EncodingCache.UTF8NoBOM, true))
|
using (BinaryReader relocsReader = new(_relocsStream, EncodingCache.UTF8NoBOM, true))
|
||||||
using (BinaryReader unwindInfosReader = new(_unwindInfosStream, EncodingCache.UTF8NoBOM, true))
|
using (BinaryReader unwindInfosReader = new(_unwindInfosStream, EncodingCache.UTF8NoBOM, true))
|
||||||
{
|
{
|
||||||
for (int i = 0; i < GetInfosEntriesCount(); i++)
|
for (int i = 0; i < infoEntriesCount; i++)
|
||||||
{
|
{
|
||||||
InfoEntry infoEntry = ReadInfo(infosReader);
|
InfoEntry infoEntry = ReadInfo(infosReader);
|
||||||
|
|
||||||
|
@ -570,6 +572,8 @@ namespace ARMeilleure.Translation.PTC
|
||||||
StubReloc(infoEntry.RelocEntriesCount);
|
StubReloc(infoEntry.RelocEntriesCount);
|
||||||
StubUnwindInfo(unwindInfosReader);
|
StubUnwindInfo(unwindInfosReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
progressReporter.Increment();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -767,76 +771,56 @@ namespace ARMeilleure.Translation.PTC
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_translateCount = 0;
|
using (ProgressReporter progressReporter = ProgressReporter.CreateAndStart(profiledFuncsToTranslate.Count, PtcStateChanged))
|
||||||
_translateTotalCount = profiledFuncsToTranslate.Count;
|
|
||||||
|
|
||||||
PtcStateChanged?.Invoke(PtcLoadingState.Start, _translateCount, _translateTotalCount);
|
|
||||||
|
|
||||||
using AutoResetEvent progressReportEvent = new AutoResetEvent(false);
|
|
||||||
|
|
||||||
Thread progressReportThread = new Thread(ReportProgress)
|
|
||||||
{
|
{
|
||||||
Name = "Ptc.ProgressReporter",
|
void TranslateFuncs()
|
||||||
Priority = ThreadPriority.Lowest,
|
|
||||||
IsBackground = true
|
|
||||||
};
|
|
||||||
|
|
||||||
progressReportThread.Start(progressReportEvent);
|
|
||||||
|
|
||||||
void TranslateFuncs()
|
|
||||||
{
|
|
||||||
while (profiledFuncsToTranslate.TryDequeue(out var item))
|
|
||||||
{
|
{
|
||||||
ulong address = item.address;
|
while (profiledFuncsToTranslate.TryDequeue(out var item))
|
||||||
|
|
||||||
Debug.Assert(PtcProfiler.IsAddressInStaticCodeRange(address));
|
|
||||||
|
|
||||||
TranslatedFunction func = Translator.Translate(memory, jumpTable, address, item.mode, item.highCq);
|
|
||||||
|
|
||||||
bool isAddressUnique = funcs.TryAdd(address, func);
|
|
||||||
|
|
||||||
Debug.Assert(isAddressUnique, $"The address 0x{address:X16} is not unique.");
|
|
||||||
|
|
||||||
if (func.HighCq)
|
|
||||||
{
|
{
|
||||||
jumpTable.RegisterFunction(address, func);
|
ulong address = item.address;
|
||||||
|
|
||||||
|
Debug.Assert(PtcProfiler.IsAddressInStaticCodeRange(address));
|
||||||
|
|
||||||
|
TranslatedFunction func = Translator.Translate(memory, jumpTable, address, item.mode, item.highCq);
|
||||||
|
|
||||||
|
bool isAddressUnique = funcs.TryAdd(address, func);
|
||||||
|
|
||||||
|
Debug.Assert(isAddressUnique, $"The address 0x{address:X16} is not unique.");
|
||||||
|
|
||||||
|
if (func.HighCq)
|
||||||
|
{
|
||||||
|
jumpTable.RegisterFunction(address, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
progressReporter.Increment();
|
||||||
|
|
||||||
|
if (State != PtcState.Enabled)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Interlocked.Increment(ref _translateCount);
|
Translator.DisposePools();
|
||||||
|
|
||||||
if (State != PtcState.Enabled)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Translator.DisposePools();
|
int maxDegreeOfParallelism = (Environment.ProcessorCount * 3) / 4;
|
||||||
|
|
||||||
|
List<Thread> threads = new List<Thread>();
|
||||||
|
|
||||||
|
for (int i = 0; i < maxDegreeOfParallelism; i++)
|
||||||
|
{
|
||||||
|
Thread thread = new Thread(TranslateFuncs);
|
||||||
|
thread.IsBackground = true;
|
||||||
|
|
||||||
|
threads.Add(thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
threads.ForEach((thread) => thread.Start());
|
||||||
|
threads.ForEach((thread) => thread.Join());
|
||||||
|
|
||||||
|
threads.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxDegreeOfParallelism = (Environment.ProcessorCount * 3) / 4;
|
|
||||||
|
|
||||||
List<Thread> threads = new List<Thread>();
|
|
||||||
|
|
||||||
for (int i = 0; i < maxDegreeOfParallelism; i++)
|
|
||||||
{
|
|
||||||
Thread thread = new Thread(TranslateFuncs);
|
|
||||||
thread.IsBackground = true;
|
|
||||||
|
|
||||||
threads.Add(thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
threads.ForEach((thread) => thread.Start());
|
|
||||||
threads.ForEach((thread) => thread.Join());
|
|
||||||
|
|
||||||
threads.Clear();
|
|
||||||
|
|
||||||
progressReportEvent.Set();
|
|
||||||
progressReportThread.Join();
|
|
||||||
|
|
||||||
PtcStateChanged?.Invoke(PtcLoadingState.Loaded, _translateCount, _translateTotalCount);
|
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {_translateTotalCount} functions translated");
|
|
||||||
|
|
||||||
PtcJumpTable.Initialize(jumpTable);
|
PtcJumpTable.Initialize(jumpTable);
|
||||||
|
|
||||||
PtcJumpTable.ReadJumpTable(jumpTable);
|
PtcJumpTable.ReadJumpTable(jumpTable);
|
||||||
|
@ -847,27 +831,6 @@ namespace ARMeilleure.Translation.PTC
|
||||||
preSaveThread.Start();
|
preSaveThread.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReportProgress(object state)
|
|
||||||
{
|
|
||||||
const int refreshRate = 50; // ms
|
|
||||||
|
|
||||||
AutoResetEvent endEvent = (AutoResetEvent)state;
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
int newCount = _translateCount;
|
|
||||||
|
|
||||||
if (count != newCount)
|
|
||||||
{
|
|
||||||
PtcStateChanged?.Invoke(PtcLoadingState.Loading, newCount, _translateTotalCount);
|
|
||||||
count = newCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (!endEvent.WaitOne(refreshRate));
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void WriteInfoCodeRelocUnwindInfo(ulong address, ulong guestSize, bool highCq, PtcInfo ptcInfo)
|
internal static void WriteInfoCodeRelocUnwindInfo(ulong address, ulong guestSize, bool highCq, PtcInfo ptcInfo)
|
||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
|
@ -986,5 +949,103 @@ namespace ARMeilleure.Translation.PTC
|
||||||
DisposeMemoryStreams();
|
DisposeMemoryStreams();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Class for reporting PTC translation / loading item progress to the UI
|
||||||
|
/// </summary>
|
||||||
|
private class ProgressReporter : IDisposable
|
||||||
|
{
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
private volatile int _itemsProcessed;
|
||||||
|
private readonly int _itemsTotal;
|
||||||
|
|
||||||
|
private readonly AutoResetEvent _progressReportEvent;
|
||||||
|
private readonly Thread _progressReportThread;
|
||||||
|
private readonly Action<PtcLoadingState, int, int> _onPtcStateChanged;
|
||||||
|
|
||||||
|
private ProgressReporter(int totalItems, Action<PtcLoadingState, int, int> onPtcStateChanged)
|
||||||
|
{
|
||||||
|
_disposed = false;
|
||||||
|
_itemsProcessed = 0;
|
||||||
|
_itemsTotal = totalItems;
|
||||||
|
|
||||||
|
_progressReportEvent = new AutoResetEvent(false);
|
||||||
|
|
||||||
|
_progressReportThread = new Thread(ReportProgress)
|
||||||
|
{
|
||||||
|
Name = "Ptc.ProgressReporter",
|
||||||
|
Priority = ThreadPriority.Lowest,
|
||||||
|
IsBackground = true
|
||||||
|
};
|
||||||
|
|
||||||
|
_onPtcStateChanged = onPtcStateChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a progress reporter and starts the background reporting thread
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="totalItems"></param>
|
||||||
|
/// <param name="onPtcStateChanged"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static ProgressReporter CreateAndStart(int totalItems, Action<PtcLoadingState, int, int> onPtcStateChanged)
|
||||||
|
{
|
||||||
|
var reporter = new ProgressReporter(totalItems, onPtcStateChanged);
|
||||||
|
reporter.Start();
|
||||||
|
|
||||||
|
return reporter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Report progress for one item
|
||||||
|
/// </summary>
|
||||||
|
public void Increment()
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _itemsProcessed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (!_disposed)
|
||||||
|
{
|
||||||
|
_progressReportEvent.Set();
|
||||||
|
_progressReportThread.Join();
|
||||||
|
_onPtcStateChanged?.Invoke(PtcLoadingState.Loaded, 0, _itemsTotal);
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException(nameof(ProgressReporter));
|
||||||
|
}
|
||||||
|
|
||||||
|
_onPtcStateChanged?.Invoke(PtcLoadingState.Start, 0, _itemsTotal);
|
||||||
|
_progressReportThread.Start(_progressReportEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReportProgress(object state)
|
||||||
|
{
|
||||||
|
const int refreshRate = 50; // ms
|
||||||
|
|
||||||
|
AutoResetEvent endEvent = (AutoResetEvent)state;
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int newCount = _itemsProcessed;
|
||||||
|
|
||||||
|
if (count != newCount)
|
||||||
|
{
|
||||||
|
_onPtcStateChanged?.Invoke(PtcLoadingState.Loading, newCount, _itemsTotal);
|
||||||
|
count = newCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!endEvent.WaitOne(refreshRate));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue