Got at least one data fetching method working; turns out, we can't use a patched LogicStack to get the data
This commit is contained in:
121
Vendor/Swan.Lite-3.1.0/Diagnostics/Benchmark.cs
vendored
Normal file
121
Vendor/Swan.Lite-3.1.0/Diagnostics/Benchmark.cs
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Swan.Diagnostics
|
||||
{
|
||||
/// <summary>
|
||||
/// A simple benchmarking class.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// The following code demonstrates how to create a simple benchmark.
|
||||
/// <code>
|
||||
/// namespace Examples.Benchmark.Simple
|
||||
/// {
|
||||
/// using Swan.Diagnostics;
|
||||
///
|
||||
/// public class SimpleBenchmark
|
||||
/// {
|
||||
/// public static void Main()
|
||||
/// {
|
||||
/// using (Benchmark.Start("Test"))
|
||||
/// {
|
||||
/// // do some logic in here
|
||||
/// }
|
||||
///
|
||||
/// // dump results into a string
|
||||
/// var results = Benchmark.Dump();
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public static partial class Benchmark
|
||||
{
|
||||
private static readonly object SyncLock = new object();
|
||||
private static readonly Dictionary<string, List<TimeSpan>> Measures = new Dictionary<string, List<TimeSpan>>();
|
||||
|
||||
/// <summary>
|
||||
/// Starts measuring with the given identifier.
|
||||
/// </summary>
|
||||
/// <param name="identifier">The identifier.</param>
|
||||
/// <returns>A disposable object that when disposed, adds a benchmark result.</returns>
|
||||
public static IDisposable Start(string identifier) => new BenchmarkUnit(identifier);
|
||||
|
||||
/// <summary>
|
||||
/// Outputs the benchmark statistics.
|
||||
/// </summary>
|
||||
/// <returns>A string containing human-readable statistics.</returns>
|
||||
public static string Dump()
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
|
||||
lock (SyncLock)
|
||||
{
|
||||
foreach (var kvp in Measures)
|
||||
{
|
||||
builder.Append($"BID: {kvp.Key,-30} | ")
|
||||
.Append($"CNT: {kvp.Value.Count,6} | ")
|
||||
.Append($"AVG: {kvp.Value.Average(t => t.TotalMilliseconds),8:0.000} ms. | ")
|
||||
.Append($"MAX: {kvp.Value.Max(t => t.TotalMilliseconds),8:0.000} ms. | ")
|
||||
.Append($"MIN: {kvp.Value.Min(t => t.TotalMilliseconds),8:0.000} ms. | ")
|
||||
.Append(Environment.NewLine);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.ToString().TrimEnd();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Measures the elapsed time of the given action as a TimeSpan
|
||||
/// This method uses a high precision Stopwatch if it is available.
|
||||
/// </summary>
|
||||
/// <param name="target">The target.</param>
|
||||
/// <returns>
|
||||
/// A time interval that represents a specified time, where the specification is in units of ticks.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">target.</exception>
|
||||
public static TimeSpan BenchmarkAction(Action target)
|
||||
{
|
||||
if (target == null)
|
||||
throw new ArgumentNullException(nameof(target));
|
||||
|
||||
var sw = Stopwatch.IsHighResolution ? new HighResolutionTimer() : new Stopwatch();
|
||||
|
||||
try
|
||||
{
|
||||
sw.Start();
|
||||
target.Invoke();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// swallow
|
||||
}
|
||||
finally
|
||||
{
|
||||
sw.Stop();
|
||||
}
|
||||
|
||||
return TimeSpan.FromTicks(sw.ElapsedTicks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified result to the given identifier.
|
||||
/// </summary>
|
||||
/// <param name="identifier">The identifier.</param>
|
||||
/// <param name="elapsed">The elapsed.</param>
|
||||
private static void Add(string identifier, TimeSpan elapsed)
|
||||
{
|
||||
lock (SyncLock)
|
||||
{
|
||||
if (Measures.ContainsKey(identifier) == false)
|
||||
Measures[identifier] = new List<TimeSpan>(1024 * 1024);
|
||||
|
||||
Measures[identifier].Add(elapsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
50
Vendor/Swan.Lite-3.1.0/Diagnostics/BenchmarkUnit.cs
vendored
Normal file
50
Vendor/Swan.Lite-3.1.0/Diagnostics/BenchmarkUnit.cs
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Swan.Diagnostics
|
||||
{
|
||||
public static partial class Benchmark
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a disposable benchmark unit.
|
||||
/// </summary>
|
||||
/// <seealso cref="IDisposable" />
|
||||
private sealed class BenchmarkUnit : IDisposable
|
||||
{
|
||||
private readonly string _identifier;
|
||||
private bool _isDisposed; // To detect redundant calls
|
||||
private Stopwatch? _stopwatch = new Stopwatch();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BenchmarkUnit" /> class.
|
||||
/// </summary>
|
||||
/// <param name="identifier">The identifier.</param>
|
||||
public BenchmarkUnit(string identifier)
|
||||
{
|
||||
_identifier = identifier;
|
||||
_stopwatch?.Start();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose() => Dispose(true);
|
||||
|
||||
/// <summary>
|
||||
/// Releases unmanaged and - optionally - managed resources.
|
||||
/// </summary>
|
||||
/// <param name="alsoManaged"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
|
||||
private void Dispose(bool alsoManaged)
|
||||
{
|
||||
if (_isDisposed) return;
|
||||
|
||||
if (alsoManaged)
|
||||
{
|
||||
Add(_identifier, _stopwatch?.Elapsed ?? default);
|
||||
_stopwatch?.Stop();
|
||||
}
|
||||
|
||||
_stopwatch = null;
|
||||
_isDisposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Vendor/Swan.Lite-3.1.0/Diagnostics/HighResolutionTimer.cs
vendored
Normal file
32
Vendor/Swan.Lite-3.1.0/Diagnostics/HighResolutionTimer.cs
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
namespace Swan.Diagnostics
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to a high-resolution, time measuring device.
|
||||
/// </summary>
|
||||
/// <seealso cref="Stopwatch" />
|
||||
public class HighResolutionTimer : Stopwatch
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HighResolutionTimer"/> class.
|
||||
/// </summary>
|
||||
/// <exception cref="NotSupportedException">High-resolution timer not available.</exception>
|
||||
public HighResolutionTimer()
|
||||
{
|
||||
if (!IsHighResolution)
|
||||
throw new NotSupportedException("High-resolution timer not available");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of microseconds per timer tick.
|
||||
/// </summary>
|
||||
public static double MicrosecondsPerTick { get; } = 1000000d / Frequency;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the elapsed microseconds.
|
||||
/// </summary>
|
||||
public long ElapsedMicroseconds => (long)(ElapsedTicks * MicrosecondsPerTick);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user