Merge branch 'profiling' into actually_profiling

This commit is contained in:
Andy Adshead 2019-02-02 11:07:14 +00:00
commit 7fcc63c1b1
3 changed files with 52 additions and 15 deletions

View file

@ -1,9 +1,8 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Ryujinx.Common;
namespace Ryujinx.Profiler
@ -48,38 +47,44 @@ namespace Ryujinx.Profiler
_history = history;
_cleanupRunning = true;
// Create low priority cleanup thread, it only cleans up RAM hence the low priority
_cleanupThread = new Thread(CleanupLoop)
{
Priority = ThreadPriority.Lowest
};
// Create cleanup thread.
_cleanupThread = new Thread(CleanupLoop);
_cleanupThread.Start();
}
private void CleanupLoop()
{
bool queueCleared = false;
while (_cleanupRunning)
{
// Ensure we only ever have 1 instance modifying timers or timerQueue
if (Monitor.TryEnter(_timerQueueClearLock))
{
ClearTimerQueue();
queueCleared = ClearTimerQueue();
foreach (var timer in Timers)
{
timer.Value.Cleanup(PerformanceCounter.ElapsedTicks - _history, _preserve - _history, _preserve);
}
// Calculate before foreach to mitigate redundant calculations
long cleanupBefore = PerformanceCounter.ElapsedTicks - _history;
long preserveStart = _preserve - _history;
// Each cleanup is self contained so run in parallel for maximum efficiency
Parallel.ForEach(Timers, (t) => t.Value.Cleanup(cleanupBefore, preserveStart, _preserve));
Monitor.Exit(_timerQueueClearLock);
}
// No need to run too often
Thread.Sleep(5);
// Only sleep if queue was sucessfully cleared
if (queueCleared)
{
Thread.Sleep(5);
}
}
}
private void ClearTimerQueue()
private bool ClearTimerQueue()
{
int count = 0;
while (_timerQueue.TryDequeue(out var item))
{
if (!Timers.TryGetValue(item.Config, out var value))
@ -96,7 +101,15 @@ namespace Ryujinx.Profiler
{
value.End(item.Time);
}
// Don't block for too long as memory disposal is blocked while this function runs
if (count++ > 10000)
{
return false;
}
}
return true;
}
public void FlagTime(TimingFlagType flagType)

View file

@ -69,6 +69,27 @@ namespace Ryujinx.Profiler
return _cachedSession;
}
}
/// <summary>
/// This equals overload is vital
/// The default comparison is far too slow for the number of comparisons needed because it doesn't know what's important to compare
/// </summary>
/// <param name="obj">Object to compare to</param>
/// <returns></returns>
public override bool Equals(object obj)
{
if (!(obj is ProfileConfig))
return false;
ProfileConfig cmpObj = (ProfileConfig)obj;
// Order here is important.
// Multiple entries with the same item is considerable less likely that multiple items with the same group.
// Likewise for group and category.
return (cmpObj.SessionItem == SessionItem &&
cmpObj.SessionGroup == SessionGroup &&
cmpObj.Category == Category);
}
}
/// <summary>

View file

@ -62,7 +62,10 @@ namespace Ryujinx.Profiler.UI
// Skip rendering out of bounds bars
if (top < 0 || bottom > Height)
{
verticalIndex++;
continue;
}
GL.Color3(Color.Green);