2019-04-26 06:53:10 +02:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
|
|
|
|
namespace Ryujinx.Profiler
|
|
|
|
|
{
|
|
|
|
|
public struct Timestamp
|
|
|
|
|
{
|
|
|
|
|
public long BeginTime;
|
|
|
|
|
public long EndTime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class TimingInfo
|
|
|
|
|
{
|
|
|
|
|
// Timestamps
|
|
|
|
|
public long TotalTime { get; set; }
|
|
|
|
|
public long Instant { get; set; }
|
|
|
|
|
|
|
|
|
|
// Measurement counts
|
|
|
|
|
public int Count { get; set; }
|
|
|
|
|
public int InstantCount { get; set; }
|
|
|
|
|
|
|
|
|
|
// Work out average
|
|
|
|
|
public long AverageTime => (Count == 0) ? -1 : TotalTime / Count;
|
|
|
|
|
|
|
|
|
|
// Intentionally not locked as it's only a get count
|
|
|
|
|
public bool IsActive => _timestamps.Count > 0;
|
|
|
|
|
|
|
|
|
|
public long BeginTime
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
lock (_timestampLock)
|
|
|
|
|
{
|
|
|
|
|
if (_depth > 0)
|
|
|
|
|
{
|
|
|
|
|
return _currentTimestamp.BeginTime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Timestamp collection
|
|
|
|
|
private List<Timestamp> _timestamps;
|
|
|
|
|
private readonly object _timestampLock = new object();
|
|
|
|
|
private readonly object _timestampListLock = new object();
|
|
|
|
|
private Timestamp _currentTimestamp;
|
|
|
|
|
|
|
|
|
|
// Depth of current timer,
|
|
|
|
|
// each begin call increments and each end call decrements
|
|
|
|
|
private int _depth;
|
|
|
|
|
|
|
|
|
|
public TimingInfo()
|
|
|
|
|
{
|
|
|
|
|
_timestamps = new List<Timestamp>();
|
|
|
|
|
_depth = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Begin(long beginTime)
|
|
|
|
|
{
|
|
|
|
|
lock (_timestampLock)
|
|
|
|
|
{
|
|
|
|
|
// Finish current timestamp if already running
|
|
|
|
|
if (_depth > 0)
|
|
|
|
|
{
|
|
|
|
|
EndUnsafe(beginTime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BeginUnsafe(beginTime);
|
|
|
|
|
_depth++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void BeginUnsafe(long beginTime)
|
|
|
|
|
{
|
|
|
|
|
_currentTimestamp.BeginTime = beginTime;
|
|
|
|
|
_currentTimestamp.EndTime = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void End(long endTime)
|
|
|
|
|
{
|
|
|
|
|
lock (_timestampLock)
|
|
|
|
|
{
|
|
|
|
|
_depth--;
|
|
|
|
|
|
|
|
|
|
if (_depth < 0)
|
|
|
|
|
{
|
|
|
|
|
throw new Exception("Timing info end called without corresponding begin");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EndUnsafe(endTime);
|
|
|
|
|
|
|
|
|
|
// Still have others using this timing info so recreate start for them
|
|
|
|
|
if (_depth > 0)
|
|
|
|
|
{
|
|
|
|
|
BeginUnsafe(endTime);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void EndUnsafe(long endTime)
|
|
|
|
|
{
|
|
|
|
|
_currentTimestamp.EndTime = endTime;
|
|
|
|
|
lock (_timestampListLock)
|
|
|
|
|
{
|
|
|
|
|
_timestamps.Add(_currentTimestamp);
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-02 04:39:22 +02:00
|
|
|
|
long delta = _currentTimestamp.EndTime - _currentTimestamp.BeginTime;
|
2019-04-26 06:53:10 +02:00
|
|
|
|
TotalTime += delta;
|
|
|
|
|
Instant += delta;
|
|
|
|
|
|
|
|
|
|
Count++;
|
|
|
|
|
InstantCount++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remove any timestamps before given timestamp to free memory
|
|
|
|
|
public void Cleanup(long before, long preserveStart, long preserveEnd)
|
|
|
|
|
{
|
|
|
|
|
lock (_timestampListLock)
|
|
|
|
|
{
|
|
|
|
|
int toRemove = 0;
|
|
|
|
|
int toPreserveStart = 0;
|
|
|
|
|
int toPreserveLen = 0;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < _timestamps.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
if (_timestamps[i].EndTime < preserveStart)
|
|
|
|
|
{
|
|
|
|
|
toPreserveStart++;
|
|
|
|
|
InstantCount--;
|
|
|
|
|
Instant -= _timestamps[i].EndTime - _timestamps[i].BeginTime;
|
|
|
|
|
}
|
|
|
|
|
else if (_timestamps[i].EndTime < preserveEnd)
|
|
|
|
|
{
|
|
|
|
|
toPreserveLen++;
|
|
|
|
|
}
|
|
|
|
|
else if (_timestamps[i].EndTime < before)
|
|
|
|
|
{
|
|
|
|
|
toRemove++;
|
|
|
|
|
InstantCount--;
|
|
|
|
|
Instant -= _timestamps[i].EndTime - _timestamps[i].BeginTime;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Assume timestamps are in chronological order so no more need to be removed
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (toPreserveStart > 0)
|
|
|
|
|
{
|
|
|
|
|
_timestamps.RemoveRange(0, toPreserveStart);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (toRemove > 0)
|
|
|
|
|
{
|
|
|
|
|
_timestamps.RemoveRange(toPreserveLen, toRemove);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Timestamp[] GetAllTimestamps()
|
|
|
|
|
{
|
|
|
|
|
lock (_timestampListLock)
|
|
|
|
|
{
|
|
|
|
|
Timestamp[] returnTimestamps = new Timestamp[_timestamps.Count];
|
|
|
|
|
_timestamps.CopyTo(returnTimestamps);
|
|
|
|
|
return returnTimestamps;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|