TimingInfo.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. using System;
  2. using System.Collections.Generic;
  3. namespace Ryujinx.Profiler
  4. {
  5. public struct Timestamp
  6. {
  7. public long BeginTime;
  8. public long EndTime;
  9. }
  10. public class TimingInfo
  11. {
  12. // Timestamps
  13. public long TotalTime { get; set; }
  14. public long Instant { get; set; }
  15. // Measurement counts
  16. public int Count { get; set; }
  17. public int InstantCount { get; set; }
  18. // Work out average
  19. public long AverageTime => (Count == 0) ? -1 : TotalTime / Count;
  20. // Intentionally not locked as it's only a get count
  21. public bool IsActive => _timestamps.Count > 0;
  22. public long BeginTime
  23. {
  24. get
  25. {
  26. lock (_timestampLock)
  27. {
  28. if (_depth > 0)
  29. {
  30. return _currentTimestamp.BeginTime;
  31. }
  32. return -1;
  33. }
  34. }
  35. }
  36. // Timestamp collection
  37. private List<Timestamp> _timestamps;
  38. private readonly object _timestampLock = new object();
  39. private readonly object _timestampListLock = new object();
  40. private Timestamp _currentTimestamp;
  41. // Depth of current timer,
  42. // each begin call increments and each end call decrements
  43. private int _depth;
  44. public TimingInfo()
  45. {
  46. _timestamps = new List<Timestamp>();
  47. _depth = 0;
  48. }
  49. public void Begin(long beginTime)
  50. {
  51. lock (_timestampLock)
  52. {
  53. // Finish current timestamp if already running
  54. if (_depth > 0)
  55. {
  56. EndUnsafe(beginTime);
  57. }
  58. BeginUnsafe(beginTime);
  59. _depth++;
  60. }
  61. }
  62. private void BeginUnsafe(long beginTime)
  63. {
  64. _currentTimestamp.BeginTime = beginTime;
  65. _currentTimestamp.EndTime = -1;
  66. }
  67. public void End(long endTime)
  68. {
  69. lock (_timestampLock)
  70. {
  71. _depth--;
  72. if (_depth < 0)
  73. {
  74. throw new Exception("Timing info end called without corresponding begin");
  75. }
  76. EndUnsafe(endTime);
  77. // Still have others using this timing info so recreate start for them
  78. if (_depth > 0)
  79. {
  80. BeginUnsafe(endTime);
  81. }
  82. }
  83. }
  84. private void EndUnsafe(long endTime)
  85. {
  86. _currentTimestamp.EndTime = endTime;
  87. lock (_timestampListLock)
  88. {
  89. _timestamps.Add(_currentTimestamp);
  90. }
  91. long delta = _currentTimestamp.EndTime - _currentTimestamp.BeginTime;
  92. TotalTime += delta;
  93. Instant += delta;
  94. Count++;
  95. InstantCount++;
  96. }
  97. // Remove any timestamps before given timestamp to free memory
  98. public void Cleanup(long before, long preserveStart, long preserveEnd)
  99. {
  100. lock (_timestampListLock)
  101. {
  102. int toRemove = 0;
  103. int toPreserveStart = 0;
  104. int toPreserveLen = 0;
  105. for (int i = 0; i < _timestamps.Count; i++)
  106. {
  107. if (_timestamps[i].EndTime < preserveStart)
  108. {
  109. toPreserveStart++;
  110. InstantCount--;
  111. Instant -= _timestamps[i].EndTime - _timestamps[i].BeginTime;
  112. }
  113. else if (_timestamps[i].EndTime < preserveEnd)
  114. {
  115. toPreserveLen++;
  116. }
  117. else if (_timestamps[i].EndTime < before)
  118. {
  119. toRemove++;
  120. InstantCount--;
  121. Instant -= _timestamps[i].EndTime - _timestamps[i].BeginTime;
  122. }
  123. else
  124. {
  125. // Assume timestamps are in chronological order so no more need to be removed
  126. break;
  127. }
  128. }
  129. if (toPreserveStart > 0)
  130. {
  131. _timestamps.RemoveRange(0, toPreserveStart);
  132. }
  133. if (toRemove > 0)
  134. {
  135. _timestamps.RemoveRange(toPreserveLen, toRemove);
  136. }
  137. }
  138. }
  139. public Timestamp[] GetAllTimestamps()
  140. {
  141. lock (_timestampListLock)
  142. {
  143. Timestamp[] returnTimestamps = new Timestamp[_timestamps.Count];
  144. _timestamps.CopyTo(returnTimestamps);
  145. return returnTimestamps;
  146. }
  147. }
  148. }
  149. }