Profiling data dumped to file on close

This commit is contained in:
Andy Adshead 2019-01-23 23:11:16 +00:00
parent 5f9ba68c99
commit 48134b2027
5 changed files with 119 additions and 67 deletions

View file

@ -0,0 +1,29 @@
using System;
using System.IO;
namespace Ryujinx.Profiler
{
public static class DumpProfile
{
public static void ToFile(string path, InternalProfile profile)
{
String fileData = "";
foreach (var time in profile.Timers)
{
fileData += $"{time.Key} - " +
$"Total: {profile.ConvertTicksToMS(time.Value.TotalTime)}ms, " +
$"Average: {profile.ConvertTicksToMS(time.Value.AverageTime)}ms, " +
$"Count: {time.Value.Count}\n";
}
// Ensure file directory exists before write
FileInfo fileInfo = new FileInfo(path);
if (fileInfo == null)
throw new Exception("Unknown logging error, probably a bad file path");
if (fileInfo.Directory != null && !fileInfo.Directory.Exists)
Directory.CreateDirectory(fileInfo.Directory.FullName);
File.WriteAllText(fileInfo.FullName, fileData);
}
}
}

View file

@ -0,0 +1,65 @@
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
namespace Ryujinx.Profiler
{
public class InternalProfile
{
private Stopwatch SW;
internal ConcurrentDictionary<string, TimingInfo> Timers;
public InternalProfile()
{
Timers = new ConcurrentDictionary<string, TimingInfo>();
SW = new Stopwatch();
SW.Start();
}
public void BeginProfile(ProfileConfig config)
{
long timestamp = SW.ElapsedTicks;
Timers.AddOrUpdate(config.Name,
(string s) => CreateTimer(timestamp),
((s, info) =>
{
info.BeginTime = timestamp;
return info;
}));
}
public void EndProfile(ProfileConfig config)
{
long timestamp = SW.ElapsedTicks;
Timers.AddOrUpdate(config.Name,
(s => new TimingInfo()),
((s, time) => UpdateTimer(time, timestamp)));
}
private TimingInfo CreateTimer(long timestamp)
{
return new TimingInfo()
{
BeginTime = timestamp,
LastTime = 0,
Count = 0,
};
}
private TimingInfo UpdateTimer(TimingInfo time, long timestamp)
{
time.Count++;
time.LastTime = timestamp - time.BeginTime;
time.TotalTime += time.LastTime;
return time;
}
public double ConvertTicksToMS(long ticks)
{
return (((double)ticks) / Stopwatch.Frequency) * 1000.0;
}
}
}

View file

@ -1,23 +1,11 @@
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
namespace Ryujinx.Profiler
{
public class Profile
{
private struct TimingInfo
{
public long BeginTime, LastTime, TotalTime, Count;
public long AverageTime
{
get => (Count == 0) ? -1 : TotalTime / Count;
}
}
// Static
private static Profile ProfileInstance;
private static InternalProfile ProfileInstance;
private static ProfilerSettings Settings;
private static bool ProfilingEnabled()
@ -26,7 +14,7 @@ namespace Ryujinx.Profiler
return false;
if (ProfileInstance == null)
ProfileInstance = new Profile();
ProfileInstance = new InternalProfile();
return true;
}
@ -35,6 +23,15 @@ namespace Ryujinx.Profiler
Settings = settings;
}
public static void FinishProfiling()
{
if (!ProfilingEnabled())
return;
if (Settings.FileDumpEnabled)
DumpProfile.ToFile(Settings.DumpLocation, ProfileInstance);
}
public static void Begin(ProfileConfig config)
{
if (!ProfilingEnabled())
@ -59,58 +56,5 @@ namespace Ryujinx.Profiler
method();
End(config);
}
// Non-static
private Stopwatch SW;
private ConcurrentDictionary<string, TimingInfo> Timers;
public Profile()
{
Timers = new ConcurrentDictionary<string, TimingInfo>();
SW = new Stopwatch();
SW.Start();
}
public void BeginProfile(ProfileConfig config)
{
long timestamp = SW.ElapsedTicks;
Timers.AddOrUpdate(config.Name,
(string s) => CreateTimer(timestamp),
((s, info) =>
{
info.BeginTime = timestamp;
return info;
}));
}
public void EndProfile(ProfileConfig config)
{
long timestamp = SW.ElapsedTicks;
Timers.AddOrUpdate(config.Name,
(s => new TimingInfo()),
((s, time) => UpdateTimer(time, timestamp)));
}
private TimingInfo CreateTimer(long timestamp)
{
return new TimingInfo()
{
BeginTime = timestamp,
LastTime = 0,
Count = 0,
};
}
private TimingInfo UpdateTimer(TimingInfo time, long timestamp)
{
time.Count++;
time.LastTime = timestamp - time.BeginTime;
time.TotalTime += time.LastTime;
return time;
}
}
}

View file

@ -0,0 +1,11 @@
namespace Ryujinx.Profiler
{
public struct TimingInfo
{
public long BeginTime, LastTime, TotalTime, Count;
public long AverageTime
{
get => (Count == 0) ? -1 : TotalTime / Count;
}
}
}

View file

@ -269,6 +269,9 @@ namespace Ryujinx
_renderThread.Join();
base.OnUnload(e);
// TODO: Find a better home for this, currently only called on OGL window close
Profile.FinishProfiling();
}
protected override void OnResize(EventArgs e)