Skip to content

Commit 410f1d6

Browse files
committed
Migrated 'Diagnostics' namespace.
1 parent 6900055 commit 410f1d6

File tree

4 files changed

+312
-0
lines changed

4 files changed

+312
-0
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Reflection;
4+
5+
6+
namespace Whathecode.System.Diagnostics.Extensions
7+
{
8+
public static class Extensions
9+
{
10+
/// <summary>
11+
/// Returns all elements on which a performed action throws an exception.
12+
/// </summary>
13+
/// <typeparam name = "T">The type of the elements of the input sequence.</typeparam>
14+
/// <param name = "source">The source for this extension method.</param>
15+
/// <param name = "action">The action to verify whether it throws an exception.</param>
16+
/// <param name = "exceptionType">When not null, a specific exception type to look for.</param>
17+
/// <returns>A sequence of all elements on which the performed action threw an exception.</returns>
18+
public static IEnumerable<T> ThrowsException<T>( this IEnumerable<T> source, Action<T> action, Type exceptionType = null )
19+
{
20+
if ( exceptionType != null && !typeof( Exception ).GetTypeInfo().IsAssignableFrom( exceptionType ) )
21+
{
22+
throw new ArgumentException( "The specified exception type is not an Exception." );
23+
}
24+
25+
using ( IEnumerator<T> iterator = source.GetEnumerator() )
26+
{
27+
while ( iterator.MoveNext() )
28+
{
29+
bool threwException = false;
30+
try
31+
{
32+
action( iterator.Current );
33+
}
34+
catch ( Exception e )
35+
{
36+
if ( exceptionType == null || exceptionType.GetTypeInfo().IsAssignableFrom( e.GetType() ) )
37+
{
38+
threwException = true;
39+
}
40+
}
41+
42+
if ( threwException )
43+
{
44+
yield return iterator.Current;
45+
}
46+
}
47+
}
48+
}
49+
}
50+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System;
2+
using Whathecode.System.Algorithm;
3+
4+
5+
namespace Whathecode.System.Diagnostics
6+
{
7+
/// <summary>
8+
/// Class which measures the runtime of a given action.
9+
/// </summary>
10+
/// <remarks>
11+
/// Useful when used as follows:
12+
/// var measure = RunTime.From( "Time measure", () =>
13+
/// {
14+
/// ... statements to execute ...
15+
/// } );
16+
/// </remarks>
17+
public class RunTime
18+
{
19+
/// <summary>
20+
/// Get the time measurement from a given action.
21+
/// </summary>
22+
/// <param name = "action">The action to measure the time from.</param>
23+
/// <returns>The time measurement of the action.</returns>
24+
public static StatisticsStopwatch.Measurement From( Action action )
25+
{
26+
if ( action == null )
27+
{
28+
throw new ArgumentNullException( nameof( action ) );
29+
}
30+
31+
return From( "", action );
32+
}
33+
34+
/// <summary>
35+
/// Get the time measurement from a given action.
36+
/// </summary>
37+
/// <param name = "label">The label to indicate which measurement it is upon calling ToString() on the result.</param>
38+
/// <param name = "action">The action to measure the time from.</param>
39+
/// <returns>The time measurement of the action.</returns>
40+
public static StatisticsStopwatch.Measurement From( string label, Action action )
41+
{
42+
if ( action == null )
43+
{
44+
throw new ArgumentNullException( nameof( action ) );
45+
}
46+
47+
return From( label, action, 1 );
48+
}
49+
50+
/// <summary>
51+
/// Get the time measurement of a certain action executed an amount of times.
52+
/// </summary>
53+
/// <param name = "label">The label to indicate which measurement it is upon calling ToString().</param>
54+
/// <param name = "action">The action to measure the time from.</param>
55+
/// <param name = "times">The amount of times the action should run.</param>
56+
/// <returns>The time measurement of the executed actions.</returns>
57+
public static StatisticsStopwatch.Measurement From( string label, Action action, int times )
58+
{
59+
if ( action == null )
60+
{
61+
throw new ArgumentNullException( nameof( action ) );
62+
}
63+
if ( times < 0 )
64+
{
65+
throw new ArgumentOutOfRangeException( nameof( times ), "Should be greater than zero." );
66+
}
67+
68+
StatisticsStopwatch stopwatch = null;
69+
Loop loop = Loop.NumberOfTimes( times, action );
70+
71+
// Start a new measurement every iteration.
72+
loop.Before.First( () => stopwatch = StatisticsStopwatch.Start( label ) );
73+
loop.After.AllButLast( () => stopwatch.StartNextMeasurement() );
74+
loop.Run();
75+
76+
return stopwatch.Stop();
77+
}
78+
}
79+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
5+
6+
namespace Whathecode.System.Diagnostics
7+
{
8+
public partial class StatisticsStopwatch
9+
{
10+
/// <summary>
11+
/// Measured results from StatisticsStopwatch.
12+
/// </summary>
13+
public class Measurement
14+
{
15+
readonly DateTime _start;
16+
readonly DateTime _stop;
17+
18+
readonly string _label;
19+
20+
/// <summary>
21+
/// The total amount of time during which measurements were made.
22+
/// </summary>
23+
public TimeSpan TotalInterval { get; private set; }
24+
25+
/// <summary>
26+
/// The amount of measurements made.
27+
/// </summary>
28+
public int MeasurementCount { get; private set; }
29+
30+
/// <summary>
31+
/// The average time of the measurements.
32+
/// </summary>
33+
public TimeSpan AverageTime { get; private set; }
34+
35+
/// <summary>
36+
/// The average time of the measurements, not including the first measurement.
37+
/// This is useful when the first call takes more time than sequential calls. (E.g. caching)
38+
/// </summary>
39+
public TimeSpan AverageTimeFirstExcluded { get; private set; }
40+
41+
/// <summary>
42+
/// The total time of all the measurements.
43+
/// </summary>
44+
public TimeSpan TotalTime { get; private set; }
45+
46+
47+
/// <summary>
48+
/// Specify a new measurement.
49+
/// </summary>
50+
/// <param name = "label">The label to use for this measurement when ToString() is used.</param>
51+
/// <param name = "start">Start time of the measurement.</param>
52+
/// <param name = "stop">End time of the measurement.</param>
53+
/// <param name = "intervals">The different measured intervals.</param>
54+
public Measurement( string label, DateTime start, DateTime stop, List<TimeSpan> intervals )
55+
{
56+
if ( stop < start )
57+
{
58+
throw new ArgumentException( "The end time of the measurement should lie after the start time." );
59+
}
60+
61+
_start = start;
62+
_stop = stop;
63+
_label = label;
64+
65+
TotalInterval = _stop - _start;
66+
MeasurementCount = intervals.Count;
67+
68+
// Get total time.
69+
long totalTicks = intervals.Sum( interval => interval.Ticks );
70+
TotalTime = new TimeSpan( totalTicks );
71+
72+
// Get average times.
73+
TimeSpan noTime = new TimeSpan( 0 );
74+
if ( intervals.Count > 0 )
75+
{
76+
AverageTime = new TimeSpan( totalTicks / intervals.Count );
77+
AverageTimeFirstExcluded = intervals.Count > 1
78+
? new TimeSpan( (TotalTime.Ticks - intervals[ 0 ].Ticks) / (intervals.Count - 1) )
79+
: noTime;
80+
}
81+
else
82+
{
83+
AverageTime = noTime;
84+
AverageTimeFirstExcluded = noTime;
85+
}
86+
}
87+
88+
89+
public override string ToString()
90+
{
91+
string output = _label + ": " + AverageTime.TotalMilliseconds + "ms";
92+
93+
if ( MeasurementCount > 1 )
94+
{
95+
output += " average time of " + MeasurementCount + " executions.";
96+
97+
// Check for big difference when not including first measurement.
98+
if ( Math.Abs( AverageTime.Ticks - AverageTimeFirstExcluded.Ticks ) > AverageTimeFirstExcluded.Ticks )
99+
{
100+
output += " (" + AverageTimeFirstExcluded.TotalMilliseconds + "ms when excluding first call)";
101+
}
102+
}
103+
104+
return output;
105+
}
106+
}
107+
}
108+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
5+
6+
namespace Whathecode.System.Diagnostics
7+
{
8+
/// <summary>
9+
/// A stopwatch which can give additional statistics for timed intervals.
10+
/// </summary>
11+
public partial class StatisticsStopwatch
12+
{
13+
readonly Stopwatch _stopwatch = new Stopwatch();
14+
readonly DateTime _timingStart;
15+
readonly List<TimeSpan> _intervals = new List<TimeSpan>();
16+
17+
readonly string _label;
18+
19+
20+
StatisticsStopwatch( DateTime start, string label )
21+
{
22+
_stopwatch.Start();
23+
_timingStart = start;
24+
25+
_label = label;
26+
}
27+
28+
29+
public static StatisticsStopwatch Start()
30+
{
31+
return Start( "" );
32+
}
33+
34+
public static StatisticsStopwatch Start( string label )
35+
{
36+
if ( label == null )
37+
{
38+
throw new ArgumentNullException( nameof( label ) );
39+
}
40+
41+
return new StatisticsStopwatch( DateTime.Now, label );
42+
}
43+
44+
public void StartNextMeasurement()
45+
{
46+
// Make sure no previous measurement is running.
47+
StopCurrentMeasurement();
48+
49+
// Start new measurement.
50+
_stopwatch.Restart();
51+
}
52+
53+
void StopCurrentMeasurement()
54+
{
55+
if ( _stopwatch.IsRunning )
56+
{
57+
_stopwatch.Stop();
58+
59+
// Add new interval.
60+
_intervals.Add( new TimeSpan( _stopwatch.ElapsedTicks ) );
61+
}
62+
}
63+
64+
public Measurement Stop()
65+
{
66+
DateTime timingStop = DateTime.Now;
67+
68+
// When a previous measurement was still running, stop it first and add interval.
69+
StopCurrentMeasurement();
70+
71+
// Return latest updated measurement.
72+
return new Measurement( _label, _timingStart, timingStop, _intervals );
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)