зеркало из https://github.com/aspnet/Stress.git
added some simple metrics recording
This commit is contained in:
Родитель
2b4f8e0882
Коммит
0f167af7f0
|
@ -3,7 +3,7 @@ using System.Diagnostics;
|
|||
|
||||
namespace Microsoft.AspNet.StressFramework
|
||||
{
|
||||
public class CpuTime
|
||||
public struct CpuTime
|
||||
{
|
||||
public TimeSpan KernelTime { get; }
|
||||
public TimeSpan UserTime { get; }
|
||||
|
@ -14,12 +14,11 @@ namespace Microsoft.AspNet.StressFramework
|
|||
UserTime = userTime;
|
||||
}
|
||||
|
||||
public static CpuTime Capture()
|
||||
public static CpuTime Capture(Process process)
|
||||
{
|
||||
var me = Process.GetCurrentProcess();
|
||||
return new CpuTime(
|
||||
me.PrivilegedProcessorTime,
|
||||
me.UserProcessorTime);
|
||||
process.PrivilegedProcessorTime,
|
||||
process.UserProcessorTime);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Microsoft.AspNet.StressFramework.Collectors
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
||||
public class CpuTimeCollectorAttribute : Attribute, ICollector
|
||||
{
|
||||
public void Initialize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void BeginIteration(StressTestIterationContext iteration)
|
||||
{
|
||||
iteration.Record(CpuTime.Capture());
|
||||
}
|
||||
|
||||
public void EndIteration(StressTestIterationContext iteration)
|
||||
{
|
||||
iteration.Record(CpuTime.Capture());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.StressFramework.Collectors
|
||||
{
|
||||
public class DataPoint
|
||||
{
|
||||
private DataPoint(DateTime timestampUtc, object value)
|
||||
{
|
||||
TimestampUtc = timestampUtc;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public DateTime TimestampUtc { get; }
|
||||
public object Value { get; }
|
||||
|
||||
public static DataPoint Create(object value)
|
||||
{
|
||||
return new DataPoint(DateTime.UtcNow, value);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[{TimestampUtc.ToLocalTime().ToString("O")}] {Value}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.StressFramework.Collectors
|
||||
{
|
||||
public struct ElapsedTime
|
||||
{
|
||||
public TimeSpan Elapsed { get; }
|
||||
|
||||
public ElapsedTime(TimeSpan elapsed)
|
||||
{
|
||||
Elapsed = elapsed;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.AspNet.StressFramework
|
||||
{
|
||||
public class MemorySnapshot
|
||||
{
|
||||
public long HeapMemoryBytes { get; }
|
||||
public long WorkingSet { get; }
|
||||
public long PrivateBytes { get; }
|
||||
|
||||
public MemorySnapshot(long heapMemoryBytes, long workingSet, long privateBytes)
|
||||
{
|
||||
HeapMemoryBytes = heapMemoryBytes;
|
||||
WorkingSet = workingSet;
|
||||
PrivateBytes = privateBytes;
|
||||
}
|
||||
|
||||
public static MemorySnapshot Capture()
|
||||
{
|
||||
var me = Process.GetCurrentProcess();
|
||||
return new MemorySnapshot(
|
||||
GC.GetTotalMemory(forceFullCollection: false),
|
||||
me.WorkingSet64,
|
||||
me.PrivateMemorySize64);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Heap: {HeapMemoryBytes / 1024.0:0.00}KB, WorkingSet: {WorkingSet / 1024.0:0.00}KB, Private: {PrivateBytes / 1024.0:0.00}KB";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.AspNet.StressFramework
|
||||
{
|
||||
public struct MemoryUsage
|
||||
{
|
||||
public long HeapMemoryBytes { get; }
|
||||
public long WorkingSet { get; }
|
||||
public long PrivateBytes { get; }
|
||||
|
||||
public MemoryUsage(long heapMemoryBytes, long workingSet, long privateBytes)
|
||||
{
|
||||
HeapMemoryBytes = heapMemoryBytes;
|
||||
WorkingSet = workingSet;
|
||||
PrivateBytes = privateBytes;
|
||||
}
|
||||
|
||||
public static MemoryUsage Capture(Process process)
|
||||
{
|
||||
// Get the GC to run fully
|
||||
for(int i = 0; i < 5; i++)
|
||||
{
|
||||
GC.GetTotalMemory(forceFullCollection: true);
|
||||
}
|
||||
var heap = GC.GetTotalMemory(forceFullCollection: true);
|
||||
|
||||
return new MemoryUsage(
|
||||
heap,
|
||||
process.WorkingSet64,
|
||||
process.PrivateMemorySize64);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Heap: {HeapMemoryBytes / 1024.0:0.00}KB, WorkingSet: {WorkingSet / 1024.0:0.00}KB, Private: {PrivateBytes / 1024.0:0.00}KB";
|
||||
}
|
||||
|
||||
public static MemoryUsage Compare(MemoryUsage start, MemoryUsage end)
|
||||
{
|
||||
return new MemoryUsage(
|
||||
end.HeapMemoryBytes - start.HeapMemoryBytes,
|
||||
end.WorkingSet - start.WorkingSet,
|
||||
end.PrivateBytes - start.PrivateBytes);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
|
||||
namespace Microsoft.AspNet.StressFramework.Collectors
|
||||
{
|
||||
public class Metric
|
||||
{
|
||||
private Metric(DateTime timestampUtc, int iteration, object value)
|
||||
{
|
||||
Value = value;
|
||||
Iteration = iteration;
|
||||
TimestampUtc = timestampUtc;
|
||||
}
|
||||
|
||||
public object Value { get; }
|
||||
public int Iteration { get; }
|
||||
public DateTime TimestampUtc { get; }
|
||||
|
||||
public static Metric Create(int iteration, object value)
|
||||
{
|
||||
return new Metric(DateTime.UtcNow, iteration, value);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[{Iteration}|{TimestampUtc.ToLocalTime().ToString("O")}] {Value}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNet.StressFramework.Collectors
|
||||
{
|
||||
public class MetricsRecordedMessage : IMessageSinkMessage
|
||||
{
|
||||
private ITest Test { get; }
|
||||
private IReadOnlyList<Metric> Metrics { get; }
|
||||
|
||||
public MetricsRecordedMessage(ITest test, IEnumerable<Metric> metrics)
|
||||
{
|
||||
Test = test;
|
||||
Metrics = metrics.ToList().AsReadOnly();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Microsoft.AspNet.StressFramework.Collectors
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
|
||||
public class TotalMemoryCollectorAttribute : Attribute, ICollector
|
||||
{
|
||||
public void Initialize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void BeginIteration(StressTestIterationContext iteration)
|
||||
{
|
||||
iteration.Record(MemorySnapshot.Capture());
|
||||
}
|
||||
|
||||
public void EndIteration(StressTestIterationContext iteration)
|
||||
{
|
||||
iteration.Record(MemorySnapshot.Capture());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,28 +1,45 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNet.StressFramework.Collectors;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.AspNet.StressFramework
|
||||
{
|
||||
public class StressTestIterationContext
|
||||
{
|
||||
private IList<ICollector> _collectors;
|
||||
private List<DataPoint> _recordings = new List<DataPoint>();
|
||||
private Stopwatch _stopwatch;
|
||||
private readonly IList<ICollector> _collectors;
|
||||
private readonly Stopwatch _stopwatch = new Stopwatch();
|
||||
private readonly List<Metric> _recordings = new List<Metric>();
|
||||
private readonly IMessageBus _bus;
|
||||
private readonly Process _me;
|
||||
|
||||
public StressTestIterationContext(IList<ICollector> collectors)
|
||||
private MemoryUsage _startMemory;
|
||||
private MemoryUsage _endMemory;
|
||||
private CpuTime _startCpu;
|
||||
|
||||
public IReadOnlyList<Metric> Recordings { get; }
|
||||
public int Iteration { get; }
|
||||
|
||||
public StressTestIterationContext(int iteration, IList<ICollector> collectors, IMessageBus bus)
|
||||
{
|
||||
Iteration = iteration;
|
||||
|
||||
_collectors = collectors;
|
||||
_bus = bus;
|
||||
_me = Process.GetCurrentProcess();
|
||||
|
||||
// The read-only wrapper IS live updated by changes to the underlying list
|
||||
// https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(System.Collections.Generic.List`1.AsReadOnly);k(SolutionItemsProject);k(DevLang-csharp)&rd=true
|
||||
Recordings = _recordings.AsReadOnly();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Record a data point
|
||||
/// Record a metric
|
||||
/// </summary>
|
||||
public void Record<T>(T data)
|
||||
{
|
||||
var dataPoint = DataPoint.Create(data);
|
||||
_recordings.Add(dataPoint);
|
||||
var metric = Metric.Create(Iteration, data);
|
||||
_recordings.Add(metric);
|
||||
}
|
||||
|
||||
public void BeginIteration()
|
||||
|
@ -32,13 +49,30 @@ namespace Microsoft.AspNet.StressFramework
|
|||
collector.BeginIteration(this);
|
||||
}
|
||||
|
||||
_stopwatch = Stopwatch.StartNew();
|
||||
// Capture memory usage after everything to ensure we miss any allocations due to collectors
|
||||
_startMemory = MemoryUsage.Capture(_me);
|
||||
|
||||
// Now capture CPU Time, which is a struct so it should have a minimal impact on memory
|
||||
_startCpu = CpuTime.Capture(_me);
|
||||
|
||||
// Start capturing elapsed time
|
||||
_stopwatch.Start();
|
||||
}
|
||||
|
||||
public void EndIteration()
|
||||
{
|
||||
// Stop capturing elapsed time
|
||||
_stopwatch.Stop();
|
||||
|
||||
// Capture CPU time
|
||||
|
||||
// Capture memory usage again, before stopping collectors to ensure we miss their allocations
|
||||
_endMemory = MemoryUsage.Capture();
|
||||
|
||||
// Record the elapsed time and memory usage
|
||||
_recordings.Add(Metric.Create(Iteration, new ElapsedTime(_stopwatch.Elapsed)));
|
||||
_recordings.Add(Metric.Create(Iteration, MemoryUsage.Compare(_startMemory, _endMemory)));
|
||||
|
||||
foreach (var collector in _collectors)
|
||||
{
|
||||
collector.EndIteration(this);
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNet.Stress.Tests
|
|||
public class SmokeTest
|
||||
{
|
||||
[StressTest]
|
||||
[TotalMemoryCollector]
|
||||
[ElapsedTimeUnder(Seconds = 1)]
|
||||
public void SmokeyMcSmokeTest()
|
||||
{
|
||||
Assert.True(true);
|
||||
|
|
Загрузка…
Ссылка в новой задаче