Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added Build/Profiler.zip
Binary file not shown.
10 changes: 8 additions & 2 deletions Profiler/Basics/BaseProfiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public abstract class BaseProfiler<K> : IProfiler, IDisposable

ulong _startFrameCount;
DateTime _startTime;
ulong _endFrameCount;
DateTime _endTime;
bool _ended;

protected BaseProfiler()
Expand All @@ -49,6 +51,8 @@ public virtual void MarkStart()
/// </summary>
public virtual void MarkEnd()
{
_endFrameCount = VRageUtils.CurrentGameFrameCount;
_endTime = DateTime.UtcNow;
_ended = true;
}

Expand Down Expand Up @@ -91,8 +95,10 @@ void IProfiler.ReceiveProfilerResult(in ProfilerResult profilerResult)
/// <returns></returns>
public BaseProfilerResult<K> GetResult()
{
var totalFrameCount = VRageUtils.CurrentGameFrameCount - _startFrameCount;
var totalTime = (DateTime.UtcNow - _startTime).TotalMilliseconds;
var endFrame = _ended ? _endFrameCount : VRageUtils.CurrentGameFrameCount;
var endTime = _ended ? _endTime : DateTime.UtcNow;
var totalFrameCount = endFrame - _startFrameCount;
var totalTime = (endTime - _startTime).TotalMilliseconds;

// copy here so that we wont have concurrency issues down the road
// https://stackoverflow.com/questions/11692389
Expand Down
3 changes: 2 additions & 1 deletion Profiler/Basics/PlayerProfiler.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using Profiler.Core;
using Sandbox.Game.Entities;
using Sandbox.Game.World;
Expand All @@ -25,7 +26,7 @@ protected override void Accept(in ProfilerResult profilerResult, ICollection<MyI
{
if (_mask.TestAll(grid))
{
foreach (var ownerId in grid.BigOwners)
foreach (var ownerId in grid.BigOwners.ToList())
{
if (MySession.Static.Players.TryGetIdentity(ownerId) is { } player)
{
Expand Down
2 changes: 1 addition & 1 deletion Profiler/Core.Patches/MyPhysics_StepWorlds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static class MyPhysics_StepWorlds
static readonly int MethodIndex = StringIndexer.Instance.IndexOf($"{typeof(MyPhysics).FullName}#StepSingleWorld");
static readonly MyConcurrentHashSet<object> _flags = new();

static bool _simulatesParallel = true;
static volatile bool _simulatesParallel = true;

public static void FlagContinuous(object flag)
{
Expand Down
132 changes: 0 additions & 132 deletions Profiler/Core/FastConcurrentQueue.cs

This file was deleted.

50 changes: 32 additions & 18 deletions Profiler/Core/ProfilerResultQueue.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using NLog;
Expand All @@ -13,12 +14,12 @@ namespace Profiler.Core
public static class ProfilerResultQueue
{
static readonly ILogger Log = LogManager.GetCurrentClassLogger();
static readonly FastConcurrentQueue<ProfilerResult> _profilerResults;
static readonly ConcurrentQueue<ProfilerResult> _profilerResults;
static readonly ConcurrentCachingList<IProfiler> _profilers;

static ProfilerResultQueue()
{
_profilerResults = new FastConcurrentQueue<ProfilerResult>();
_profilerResults = new ConcurrentQueue<ProfilerResult>();
_profilers = new ConcurrentCachingList<IProfiler>();
}

Expand All @@ -35,35 +36,48 @@ public static IDisposable Profile(IProfiler observer)

internal static void Enqueue(in ProfilerResult result)
{
if (_profilers.Count == 0) return;

_profilerResults.Enqueue(result);
}

internal static async Task Start(CancellationToken canceller)
{
while (!canceller.IsCancellationRequested)
{
_profilerResults.Alternate();
_profilers.ApplyChanges();

var index = 0;
while (_profilerResults.TryDequeue(ref index, out var result))
try
{
foreach (var profiler in _profilers)
_profilers.ApplyChanges();

var dequeued = false;
while (_profilerResults.TryDequeue(out var result))
{
try
dequeued = true;
foreach (var profiler in _profilers)
{
profiler.ReceiveProfilerResult(result);
}
catch (Exception e)
{
Log.Error($"{profiler}: {e.Message}");
try
{
profiler.ReceiveProfilerResult(result);
}
catch (Exception e)
{
Log.Error($"{profiler}: {e.Message}");
}
}
}
}

await Task.Delay(TimeSpan.FromSeconds(.1f), canceller);
if (!dequeued)
{
await Task.Delay(TimeSpan.FromSeconds(.1f), canceller);
}
}
catch (OperationCanceledException) when (canceller.IsCancellationRequested)
{
break;
}
catch (Exception e)
{
Log.Warn(e, "Profiler consumer loop crashed; restarting after delay");
await Task.Delay(TimeSpan.FromSeconds(1), canceller);
}
}
}

Expand Down
23 changes: 15 additions & 8 deletions Profiler/Core/StringIndexer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ internal sealed class StringIndexer
public static readonly StringIndexer Instance = new StringIndexer();

readonly List<string> _mapping;
readonly object _lock = new object();

StringIndexer()
{
Expand All @@ -24,21 +25,27 @@ public int IndexOf(string methodName)
throw new Exception("method name null");
}

var existingIndex = _mapping.IndexOf(methodName);
if (existingIndex >= 0) return existingIndex;
lock (_lock)
{
var existingIndex = _mapping.IndexOf(methodName);
if (existingIndex >= 0) return existingIndex;

_mapping.Add(methodName);
return _mapping.Count - 1;
_mapping.Add(methodName);
return _mapping.Count - 1;
}
}

public string StringAt(int index)
{
if (index >= _mapping.Count)
lock (_lock)
{
throw new IndexOutOfRangeException($"length: {_mapping.Count}, given index: {index}");
}
if (index >= _mapping.Count)
{
throw new IndexOutOfRangeException($"length: {_mapping.Count}, given index: {index}");
}

return _mapping[index];
return _mapping[index];
}
}
}
}
62 changes: 62 additions & 0 deletions Profiler/DiagnoseResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System.Collections.Generic;

namespace Profiler
{
public class DiagnoseResult
{
public ulong TotalFrameCount { get; set; }
public double TotalTimeMs { get; set; }
public Dictionary<string, double> FrameCategories { get; set; }
public List<GridEntry> TopGrids { get; set; }
public List<BlockTypeEntry> TopBlockTypes { get; set; }
public List<PlayerEntry> TopPlayers { get; set; }
public List<FactionEntry> TopFactions { get; set; }
public List<ClusterEntry> TopClusters { get; set; }
public List<SessionEntry> TopSessionComponents { get; set; }
}

public class GridEntry
{
public string Name { get; set; }
public long EntityId { get; set; }
public double MsPerFrame { get; set; }
public int BlockCount { get; set; }
}

public class BlockTypeEntry
{
public string TypeName { get; set; }
public double MsPerFrame { get; set; }
}

public class PlayerEntry
{
public string Name { get; set; }
public long IdentityId { get; set; }
public double MsPerFrame { get; set; }
public int GridCount { get; set; }
}

public class FactionEntry
{
public string Tag { get; set; }
public long FactionId { get; set; }
public double MsPerFrame { get; set; }
public int GridCount { get; set; }
}

public class ClusterEntry
{
public int Index { get; set; }
public int GridCount { get; set; }
public double SizeKm { get; set; }
public double MsPerFrame { get; set; }
public List<GridEntry> TopGrids { get; set; }
}

public class SessionEntry
{
public string ComponentName { get; set; }
public double MsPerFrame { get; set; }
}
}
2 changes: 0 additions & 2 deletions Profiler/Interactive/PhysicsEntitySnapshot.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using Utils.General;
using Sandbox.Game.Entities;
using Sandbox.Game.Entities.Cube;
using Sandbox.Game.Entities.EnvironmentItems;
using Sandbox.Game.World;
using VRage.Game.Entity;
using VRage.Game.ModAPI;
Expand Down
Loading