From 9331d4825601f93d2fcabfb32cdd87cd5a22d9b1 Mon Sep 17 00:00:00 2001 From: Ian Qvist Date: Thu, 13 Apr 2017 16:32:04 +0200 Subject: [PATCH] Some work on #5 --- .../Primitives/Optimization/IPoolable.cs | 9 +++ SourceFiles/Utils/Benchmark.cs | 51 ++++++++++++ SourceFiles/Utils/BenchmarkRun.cs | 39 +++++++++ SourceFiles/Utils/Pool.cs | 80 +++++++++++++++++++ 4 files changed, 179 insertions(+) create mode 100644 SourceFiles/Primitives/Optimization/IPoolable.cs create mode 100644 SourceFiles/Utils/Benchmark.cs create mode 100644 SourceFiles/Utils/BenchmarkRun.cs create mode 100644 SourceFiles/Utils/Pool.cs diff --git a/SourceFiles/Primitives/Optimization/IPoolable.cs b/SourceFiles/Primitives/Optimization/IPoolable.cs new file mode 100644 index 000000000..922f6e417 --- /dev/null +++ b/SourceFiles/Primitives/Optimization/IPoolable.cs @@ -0,0 +1,9 @@ +using System; + +namespace VelcroPhysics.Primitives.Optimization +{ + public interface IPoolable : IDisposable + { + void Reset(); + } +} diff --git a/SourceFiles/Utils/Benchmark.cs b/SourceFiles/Utils/Benchmark.cs new file mode 100644 index 000000000..889b30abf --- /dev/null +++ b/SourceFiles/Utils/Benchmark.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; + +namespace VelcroPhysics.Utils +{ + public static class Benchmark + { + private static readonly Dictionary _results = new Dictionary(); + private static readonly Pool _runPool = new Pool(1); + + public static BenchmarkRun StartRun(string area) + { + BenchmarkRun run = _runPool.GetFromPool(); + run.SetData(area); + return run; + } + + public static void RecordResults(string area, long results) + { + if (!Settings.EnableDiagnostics) + return; + + if (!_results.ContainsKey(area)) + _results.Add(area, results); + else + _results[area] += results; + } + + public static long ResetResults(string area) + { + if (!Settings.EnableDiagnostics) + return 0; + + long oldVal = _results[area]; + _results[area] = 0; + return oldVal; + } + + public static long GetResults(string area) + { + if (!Settings.EnableDiagnostics) + return 0; + + return _results.TryGetValue(area, out long value) ? value : 0; + } + + internal static void ReturnToPool(BenchmarkRun run) + { + _runPool.ReturnToPool(run); + } + } +} diff --git a/SourceFiles/Utils/BenchmarkRun.cs b/SourceFiles/Utils/BenchmarkRun.cs new file mode 100644 index 000000000..b50699818 --- /dev/null +++ b/SourceFiles/Utils/BenchmarkRun.cs @@ -0,0 +1,39 @@ +using System.Diagnostics; +using VelcroPhysics.Primitives.Optimization; + +namespace VelcroPhysics.Utils +{ + public class BenchmarkRun : IPoolable + { + private string _area; + private readonly Stopwatch _stopwatch = new Stopwatch(); + private bool _resultsRecorded; + + public void SetData(string area) + { + _area = area; + _stopwatch.Start(); + } + + public void Dispose() + { + RecordResults(); + Benchmark.ReturnToPool(this); + } + + public void RecordResults() + { + if (_resultsRecorded) + return; + + _stopwatch.Stop(); + Benchmark.RecordResults(_area, _stopwatch.ElapsedTicks); + _resultsRecorded = true; + } + + public void Reset() + { + _stopwatch.Reset(); + } + } +} \ No newline at end of file diff --git a/SourceFiles/Utils/Pool.cs b/SourceFiles/Utils/Pool.cs new file mode 100644 index 000000000..4e2ff68dc --- /dev/null +++ b/SourceFiles/Utils/Pool.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using VelcroPhysics.Primitives.Optimization; + +namespace VelcroPhysics.Utils +{ + public class Pool where T : class, IPoolable, new() + { + private readonly Queue _queue; + + public Pool(int capacity, bool createInstances = true) + { + _queue = new Queue(capacity); + + if (createInstances) + { + for (int i = 0; i < capacity; i++) + { + _queue.Enqueue(new T()); + } + } + } + + public T GetFromPool() + { + if (_queue.Count <= 0) + return new T(); + + T obj = _queue.Dequeue(); + obj.Reset(); + return obj; + } + + public IEnumerable GetManyFromPool(int count) + { + int diff = count - _queue.Count; + + if (diff >= 0) + { + //We have all in queue + for (int i = 0; i < diff; i++) + { + T obj = _queue.Dequeue(); + obj.Reset(); + yield return obj; + } + } + else + { + //We need to return what is in queue and then make more + for (int i = 0; i < _queue.Count; i++) + { + T obj = _queue.Dequeue(); + obj.Reset(); + yield return obj; + } + + int remaining = Math.Abs(diff); + + for (int i = 0; i < remaining; i++) + { + yield return new T(); + } + } + } + + public void ReturnToPool(T obj) + { + _queue.Enqueue(obj); + } + + public void ReturnToPool(IEnumerable objs) + { + foreach (T obj in objs) + { + _queue.Enqueue(obj); + } + } + } +}