Enhance Profiler with Label Metrics and Rolling Windows
- Introduced LabelMetrics and RollingLabelMetrics structs to capture detailed profiling data. - Implemented a RollingWindow class to maintain a rolling average of metrics. - Updated Frame class to collect and store label metrics, including memory allocation and garbage collection statistics. - Enhanced ScopeNode class to support self-time calculations and child duration tracking. - Improved the Profiler class to manage frame budgets and rolling metrics. - Refactored the ProfilerVisualizer to support new timeline rendering features, including zoom and pan functionality. - Added tooltip support for detailed node information in the flame graph. - Enhanced BoundedQueue to be thread-safe with proper locking mechanisms for concurrent access.
This commit is contained in:
@@ -5,6 +5,7 @@ namespace Nerfed.Runtime;
|
||||
public class BoundedQueue<T> : IEnumerable<T>, ICollection, IReadOnlyCollection<T>
|
||||
{
|
||||
private readonly Queue<T> queue = null;
|
||||
private readonly object syncLock = new object();
|
||||
private readonly int maxSize = 10;
|
||||
private T lastAddedElement;
|
||||
|
||||
@@ -16,58 +17,114 @@ public class BoundedQueue<T> : IEnumerable<T>, ICollection, IReadOnlyCollection<
|
||||
|
||||
public void Enqueue(T item)
|
||||
{
|
||||
queue.Enqueue(item);
|
||||
if (queue.Count > maxSize)
|
||||
{
|
||||
queue.Dequeue(); // Remove the oldest element
|
||||
}
|
||||
Enqueue(item, out _);
|
||||
}
|
||||
|
||||
lastAddedElement = item;
|
||||
public bool Enqueue(T item, out T evictedItem)
|
||||
{
|
||||
lock (syncLock)
|
||||
{
|
||||
queue.Enqueue(item);
|
||||
if (queue.Count > maxSize)
|
||||
{
|
||||
evictedItem = queue.Dequeue();
|
||||
lastAddedElement = item;
|
||||
return true;
|
||||
}
|
||||
|
||||
evictedItem = default;
|
||||
lastAddedElement = item;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public T Dequeue()
|
||||
{
|
||||
return queue.Dequeue();
|
||||
lock (syncLock)
|
||||
{
|
||||
return queue.Dequeue();
|
||||
}
|
||||
}
|
||||
|
||||
public T Peek()
|
||||
{
|
||||
return queue.Peek();
|
||||
lock (syncLock)
|
||||
{
|
||||
return queue.Peek();
|
||||
}
|
||||
}
|
||||
|
||||
public T LastAddedElement()
|
||||
{
|
||||
return lastAddedElement;
|
||||
lock (syncLock)
|
||||
{
|
||||
return lastAddedElement;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
queue.Clear();
|
||||
lock (syncLock)
|
||||
{
|
||||
queue.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(T item)
|
||||
{
|
||||
return queue.Contains(item);
|
||||
lock (syncLock)
|
||||
{
|
||||
return queue.Contains(item);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return queue.GetEnumerator();
|
||||
T[] snapshot;
|
||||
lock (syncLock)
|
||||
{
|
||||
snapshot = queue.ToArray();
|
||||
}
|
||||
|
||||
return ((IEnumerable<T>)snapshot).GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return queue.GetEnumerator();
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public void CopyTo(Array array, int index)
|
||||
{
|
||||
((ICollection)queue).CopyTo(array, index);
|
||||
lock (syncLock)
|
||||
{
|
||||
((ICollection)queue).CopyTo(array, index);
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (syncLock)
|
||||
{
|
||||
return queue.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Count => queue.Count;
|
||||
public int Capacity => maxSize;
|
||||
public bool IsSynchronized => ((ICollection)queue).IsSynchronized;
|
||||
public object SyncRoot => ((ICollection)queue).SyncRoot;
|
||||
int IReadOnlyCollection<T>.Count => queue.Count;
|
||||
public bool IsSynchronized => true;
|
||||
public object SyncRoot => syncLock;
|
||||
|
||||
int IReadOnlyCollection<T>.Count
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (syncLock)
|
||||
{
|
||||
return queue.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user