2019-04-26 00:53:10 -04:00
|
|
|
|
using Ryujinx.Common;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Diagnostics;
|
2019-04-27 08:57:42 -04:00
|
|
|
|
using System.IO;
|
2019-04-26 00:53:10 -04:00
|
|
|
|
|
2020-02-06 06:25:47 -05:00
|
|
|
|
namespace Ryujinx.Debugger.Profiler
|
2019-04-26 00:53:10 -04:00
|
|
|
|
{
|
|
|
|
|
public static class Profile
|
|
|
|
|
{
|
|
|
|
|
public static float UpdateRate => _settings.UpdateRate;
|
|
|
|
|
public static long HistoryLength => _settings.History;
|
|
|
|
|
|
2020-04-20 17:59:59 -04:00
|
|
|
|
#pragma warning disable CS0649
|
2019-04-26 00:53:10 -04:00
|
|
|
|
private static InternalProfile _profileInstance;
|
2020-04-20 17:59:59 -04:00
|
|
|
|
#pragma warning restore CS0649
|
2019-04-26 00:53:10 -04:00
|
|
|
|
private static ProfilerSettings _settings;
|
|
|
|
|
|
2020-02-06 06:25:47 -05:00
|
|
|
|
[Conditional("USE_DEBUGGING")]
|
2019-07-01 22:39:22 -04:00
|
|
|
|
public static void Initialize()
|
2019-04-26 00:53:10 -04:00
|
|
|
|
{
|
2019-04-27 08:57:42 -04:00
|
|
|
|
var config = ProfilerConfiguration.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ProfilerConfig.jsonc"));
|
2019-04-26 00:53:10 -04:00
|
|
|
|
|
|
|
|
|
_settings = new ProfilerSettings()
|
|
|
|
|
{
|
|
|
|
|
Enabled = config.Enabled,
|
|
|
|
|
FileDumpEnabled = config.DumpPath != "",
|
|
|
|
|
DumpLocation = config.DumpPath,
|
|
|
|
|
UpdateRate = (config.UpdateRate <= 0) ? -1 : 1.0f / config.UpdateRate,
|
|
|
|
|
History = (long)(config.History * PerformanceCounter.TicksPerSecond),
|
|
|
|
|
MaxLevel = config.MaxLevel,
|
|
|
|
|
MaxFlags = config.MaxFlags,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static bool ProfilingEnabled()
|
|
|
|
|
{
|
2020-02-06 06:25:47 -05:00
|
|
|
|
#if USE_DEBUGGING
|
2019-04-26 00:53:10 -04:00
|
|
|
|
if (!_settings.Enabled)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (_profileInstance == null)
|
|
|
|
|
_profileInstance = new InternalProfile(_settings.History, _settings.MaxFlags);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
#else
|
|
|
|
|
return false;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-06 06:25:47 -05:00
|
|
|
|
[Conditional("USE_DEBUGGING")]
|
2019-04-26 00:53:10 -04:00
|
|
|
|
public static void FinishProfiling()
|
|
|
|
|
{
|
|
|
|
|
if (!ProfilingEnabled())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (_settings.FileDumpEnabled)
|
|
|
|
|
DumpProfile.ToFile(_settings.DumpLocation, _profileInstance);
|
|
|
|
|
|
|
|
|
|
_profileInstance.Dispose();
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-06 06:25:47 -05:00
|
|
|
|
[Conditional("USE_DEBUGGING")]
|
2019-04-26 00:53:10 -04:00
|
|
|
|
public static void FlagTime(TimingFlagType flagType)
|
|
|
|
|
{
|
|
|
|
|
if (!ProfilingEnabled())
|
|
|
|
|
return;
|
|
|
|
|
_profileInstance.FlagTime(flagType);
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-06 06:25:47 -05:00
|
|
|
|
[Conditional("USE_DEBUGGING")]
|
2019-07-01 22:39:22 -04:00
|
|
|
|
public static void RegisterFlagReceiver(Action<TimingFlag> receiver)
|
2019-04-26 00:53:10 -04:00
|
|
|
|
{
|
|
|
|
|
if (!ProfilingEnabled())
|
|
|
|
|
return;
|
2019-07-01 22:39:22 -04:00
|
|
|
|
_profileInstance.RegisterFlagReceiver(receiver);
|
2019-04-26 00:53:10 -04:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-06 06:25:47 -05:00
|
|
|
|
[Conditional("USE_DEBUGGING")]
|
2019-04-26 00:53:10 -04:00
|
|
|
|
public static void Begin(ProfileConfig config)
|
|
|
|
|
{
|
|
|
|
|
if (!ProfilingEnabled())
|
|
|
|
|
return;
|
|
|
|
|
if (config.Level > _settings.MaxLevel)
|
|
|
|
|
return;
|
|
|
|
|
_profileInstance.BeginProfile(config);
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-06 06:25:47 -05:00
|
|
|
|
[Conditional("USE_DEBUGGING")]
|
2019-04-26 00:53:10 -04:00
|
|
|
|
public static void End(ProfileConfig config)
|
|
|
|
|
{
|
|
|
|
|
if (!ProfilingEnabled())
|
|
|
|
|
return;
|
|
|
|
|
if (config.Level > _settings.MaxLevel)
|
|
|
|
|
return;
|
|
|
|
|
_profileInstance.EndProfile(config);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static string GetSession()
|
|
|
|
|
{
|
2020-02-06 06:25:47 -05:00
|
|
|
|
#if USE_DEBUGGING
|
2019-04-26 00:53:10 -04:00
|
|
|
|
if (!ProfilingEnabled())
|
|
|
|
|
return null;
|
|
|
|
|
return _profileInstance.GetSession();
|
|
|
|
|
#else
|
|
|
|
|
return "";
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static List<KeyValuePair<ProfileConfig, TimingInfo>> GetProfilingData()
|
|
|
|
|
{
|
2020-02-06 06:25:47 -05:00
|
|
|
|
#if USE_DEBUGGING
|
2019-04-26 00:53:10 -04:00
|
|
|
|
if (!ProfilingEnabled())
|
|
|
|
|
return new List<KeyValuePair<ProfileConfig, TimingInfo>>();
|
|
|
|
|
return _profileInstance.GetProfilingData();
|
|
|
|
|
#else
|
|
|
|
|
return new List<KeyValuePair<ProfileConfig, TimingInfo>>();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static TimingFlag[] GetTimingFlags()
|
|
|
|
|
{
|
2020-02-06 06:25:47 -05:00
|
|
|
|
#if USE_DEBUGGING
|
2019-04-26 00:53:10 -04:00
|
|
|
|
if (!ProfilingEnabled())
|
|
|
|
|
return new TimingFlag[0];
|
|
|
|
|
return _profileInstance.GetTimingFlags();
|
|
|
|
|
#else
|
|
|
|
|
return new TimingFlag[0];
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static (long[], long[]) GetTimingAveragesAndLast()
|
|
|
|
|
{
|
2020-02-06 06:25:47 -05:00
|
|
|
|
#if USE_DEBUGGING
|
2019-04-26 00:53:10 -04:00
|
|
|
|
if (!ProfilingEnabled())
|
|
|
|
|
return (new long[0], new long[0]);
|
|
|
|
|
return _profileInstance.GetTimingAveragesAndLast();
|
|
|
|
|
#else
|
|
|
|
|
return (new long[0], new long[0]);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|