public static void Initialize(string titleIdText, string displayVersion, bool enabled, MemoryManagerMode memoryMode) { Wait(); PtcProfiler.Wait(); PtcProfiler.ClearEntries(); Logger.Info?.Print(LogClass.Ptc, $"Initializing Profiled Persistent Translation Cache (enabled: {enabled})."); if (!enabled || string.IsNullOrEmpty(titleIdText) || titleIdText == TitleIdTextDefault) { TitleIdText = TitleIdTextDefault; DisplayVersion = DisplayVersionDefault; CachePathActual = string.Empty; CachePathBackup = string.Empty; Disable(); return; } TitleIdText = titleIdText; DisplayVersion = !string.IsNullOrEmpty(displayVersion) ? displayVersion : DisplayVersionDefault; _memoryMode = memoryMode; string workPathActual = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", ActualDir); string workPathBackup = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", BackupDir); if (!Directory.Exists(workPathActual)) { Directory.CreateDirectory(workPathActual); } if (!Directory.Exists(workPathBackup)) { Directory.CreateDirectory(workPathBackup); } CachePathActual = Path.Combine(workPathActual, DisplayVersion); CachePathBackup = Path.Combine(workPathBackup, DisplayVersion); PreLoad(); PtcProfiler.PreLoad(); Enable(); }
internal static void MakeAndSaveTranslations( ConcurrentDictionary <ulong, TranslatedFunction> funcs, IMemoryManager memory, JumpTable jumpTable, EntryTable <uint> countTable) { var profiledFuncsToTranslate = PtcProfiler.GetProfiledFuncsToTranslate(funcs); _translateCount = 0; _translateTotalCount = profiledFuncsToTranslate.Count; int degreeOfParallelism = new DegreeOfParallelism(4d, 75d, 12.5d).GetDegreeOfParallelism(0, 32); if (_translateTotalCount == 0 || degreeOfParallelism == 0) { ResetCarriersIfNeeded(); PtcJumpTable.ClearIfNeeded(); GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; return; } Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {_translateTotalCount} functions translated | Thread count: {degreeOfParallelism}"); PtcStateChanged?.Invoke(PtcLoadingState.Start, _translateCount, _translateTotalCount); using AutoResetEvent progressReportEvent = new AutoResetEvent(false); Thread progressReportThread = new Thread(ReportProgress) { Name = "Ptc.ProgressReporter", Priority = ThreadPriority.Lowest, IsBackground = true }; progressReportThread.Start(progressReportEvent); void TranslateFuncs() { while (profiledFuncsToTranslate.TryDequeue(out var item)) { ulong address = item.address; Debug.Assert(PtcProfiler.IsAddressInStaticCodeRange(address)); TranslatedFunction func = Translator.Translate(memory, jumpTable, countTable, address, item.funcProfile.Mode, item.funcProfile.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); } Interlocked.Increment(ref _translateCount); if (State != PtcState.Enabled) { break; } } Translator.DisposePools(); } List <Thread> threads = new List <Thread>(); for (int i = 0; i < degreeOfParallelism; 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 | Thread count: {degreeOfParallelism}"); PtcJumpTable.Initialize(jumpTable); PtcJumpTable.ReadJumpTable(jumpTable); PtcJumpTable.ReadDynamicTable(jumpTable); Thread preSaveThread = new Thread(PreSave); preSaveThread.IsBackground = true; preSaveThread.Start(); }
internal static void MakeAndSaveTranslations(ConcurrentDictionary <ulong, TranslatedFunction> funcs, IMemoryManager memory, JumpTable jumpTable) { var profiledFuncsToTranslate = PtcProfiler.GetProfiledFuncsToTranslate(funcs); if (profiledFuncsToTranslate.Count == 0) { return; } _translateCount = 0; ThreadPool.QueueUserWorkItem(TranslationLogger, profiledFuncsToTranslate.Count); void TranslateFuncs() { while (profiledFuncsToTranslate.TryDequeue(out var item)) { 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); } Interlocked.Increment(ref _translateCount); if (State != PtcState.Enabled) { break; } } } 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(); Translator.ResetPools(); _loggerEvent.Set(); PtcJumpTable.Initialize(jumpTable); PtcJumpTable.ReadJumpTable(jumpTable); PtcJumpTable.ReadDynamicTable(jumpTable); ThreadPool.QueueUserWorkItem(PreSave); }
private static void CurrentDomain_ProcessExit(object sender, EventArgs e) { Dispose(); PtcProfiler.Dispose(); }
internal static void MakeAndSaveTranslations(ConcurrentDictionary <ulong, TranslatedFunction> funcs, IMemoryManager memory, JumpTable jumpTable) { if (PtcProfiler.ProfiledFuncs.Count == 0) { return; } _translateCount = 0; _rejitCount = 0; ThreadPool.QueueUserWorkItem(TranslationLogger, (funcs.Count, PtcProfiler.ProfiledFuncs.Count)); int maxDegreeOfParallelism = (Environment.ProcessorCount * 3) / 4; Parallel.ForEach(PtcProfiler.ProfiledFuncs, new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism }, (item, state) => { ulong address = item.Key; Debug.Assert(PtcProfiler.IsAddressInStaticCodeRange(address)); if (!funcs.ContainsKey(address)) { TranslatedFunction func = Translator.Translate(memory, jumpTable, address, item.Value.mode, item.Value.highCq); funcs.TryAdd(address, func); if (func.HighCq) { jumpTable.RegisterFunction(address, func); } Interlocked.Increment(ref _translateCount); } else if (item.Value.highCq && !funcs[address].HighCq) { TranslatedFunction func = Translator.Translate(memory, jumpTable, address, item.Value.mode, highCq: true); funcs[address] = func; jumpTable.RegisterFunction(address, func); Interlocked.Increment(ref _rejitCount); } if (State != PtcState.Enabled) { state.Stop(); } }); _loggerEvent.Set(); if (_translateCount != 0 || _rejitCount != 0) { PtcJumpTable.Initialize(jumpTable); PtcJumpTable.ReadJumpTable(jumpTable); PtcJumpTable.ReadDynamicTable(jumpTable); ThreadPool.QueueUserWorkItem(PreSave); } }