| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- 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);
- }
- long delta = _currentTimestamp.EndTime - _currentTimestamp.BeginTime;
- 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;
- }
- }
- }
- }
|