Skip to content

Commit a246fa2

Browse files
committed
Merge pull request #25 from LeeCampbell/Recorder
Recorder
2 parents a840a90 + 7746fd1 commit a246fa2

14 files changed

Lines changed: 932 additions & 13 deletions

src/HdrHistogram.Examples/HdrHistogram.Examples.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
<ItemGroup>
4444
<Compile Include="Program.cs" />
4545
<Compile Include="Properties\AssemblyInfo.cs" />
46+
<Compile Include="RecorderExample.cs" />
4647
<Compile Include="SimpleHistogramExample.cs" />
4748
</ItemGroup>
4849
<ItemGroup>

src/HdrHistogram.Examples/Program.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ class Program
44
{
55
static void Main(string[] args)
66
{
7-
SimpleHistogramExample.Run();
7+
//SimpleHistogramExample.Run();
8+
RecorderExample.Run();
89
}
910
}
1011
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.IO;
4+
using System.Net;
5+
using System.Net.Sockets;
6+
using System.Threading;
7+
8+
namespace HdrHistogram.Examples
9+
{
10+
/// <summary>
11+
/// A simple example of using HdrHistogram's Recorder: run for 20 seconds collecting the
12+
/// time it takes to perform a simple Datagram Socket create/close operation,
13+
/// and report a histogram of the times at the end.
14+
/// </summary>
15+
static class RecorderExample
16+
{
17+
private static readonly Recorder Recorder = new Recorder(1, TimeSpan.TicksPerHour, 3, (id, low, high, sf) => new LongHistogram(id, low, high, sf));
18+
private static readonly Lazy<AddressFamily> AddressFamily = new Lazy<AddressFamily>(() => GetAddressFamily("google.com"));
19+
private static readonly TimeSpan RunPeriod = TimeSpan.FromSeconds(10);
20+
private static readonly LongHistogram AccumulatingHistogram = new LongHistogram(TimeSpan.TicksPerHour, 3);
21+
private const string LogPath = "DatagramSocket.histogram.log";
22+
private static HistogramLogWriter _logWriter;
23+
private static FileStream _outputStream;
24+
private static int _isCompleted = 0;
25+
26+
public static void Run()
27+
{
28+
Console.WriteLine($"Running for {RunPeriod.TotalSeconds}sec.");
29+
30+
_outputStream = File.Create(LogPath);
31+
_logWriter = new HistogramLogWriter(_outputStream);
32+
//Write the headers, but no histograms (as we don't have any yet).
33+
_logWriter.Write(DateTime.Now);
34+
35+
var outputThread = new Thread(ts => WriteToDisk());
36+
outputThread.Start();
37+
RecordMeasurements();
38+
}
39+
40+
private static void WriteToDisk()
41+
{
42+
//Sample every second until flagged as completed.
43+
while (_isCompleted == 0)
44+
{
45+
Thread.Sleep(1000);
46+
47+
var histogram = Recorder.GetIntervalHistogram();
48+
AccumulatingHistogram.Add(histogram);
49+
_logWriter.Append(histogram);
50+
Console.WriteLine($"{DateTime.Now:o} Interval.TotalCount = {histogram.TotalCount,10:G}. Accumulated.TotalCount = {AccumulatingHistogram.TotalCount,10:G}.");
51+
}
52+
_logWriter.Dispose();
53+
_outputStream.Dispose();
54+
Console.WriteLine("Log contents");
55+
Console.WriteLine(File.ReadAllText(LogPath));
56+
Console.WriteLine("Output thread finishing.");
57+
}
58+
59+
/// <summary>
60+
/// Shows a sample loop where an action is executed, and the latency of each execution is recorded.
61+
/// </summary>
62+
private static void RecordMeasurements()
63+
{
64+
var timer = Stopwatch.StartNew();
65+
Action actionToMeasure = CreateAndCloseDatagramSocket;
66+
do
67+
{
68+
Recorder.Record(actionToMeasure);
69+
} while (timer.Elapsed < RunPeriod);
70+
Interlocked.Increment(ref _isCompleted);
71+
}
72+
73+
private static void CreateAndCloseDatagramSocket()
74+
{
75+
try
76+
{
77+
using (var socket = new Socket(AddressFamily.Value, SocketType.Stream, ProtocolType.Tcp))
78+
{
79+
}
80+
}
81+
catch (SocketException)
82+
{
83+
}
84+
}
85+
86+
private static AddressFamily GetAddressFamily(string url)
87+
{
88+
var hostIpAddress = Dns.GetHostEntry(url).AddressList[0];
89+
var hostIpEndPoint = new IPEndPoint(hostIpAddress, 80);
90+
return hostIpEndPoint.AddressFamily;
91+
}
92+
}
93+
}

src/HdrHistogram.UnitTests/HdrHistogram.UnitTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
<Compile Include="Persistence\ShortHistogramLogReaderWriterTests.cs" />
6565
<Compile Include="Persistence\TestCaseGenerator.cs" />
6666
<Compile Include="Properties\AssemblyInfo.cs" />
67+
<Compile Include="RecorderTests.cs" />
6768
<Compile Include="ShortHistogramTests.cs" />
6869
</ItemGroup>
6970
<ItemGroup>

src/HdrHistogram.UnitTests/HistogramTestBase.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System;
2+
using System.IO;
3+
using System.Threading;
24
using NUnit.Framework;
35

46
namespace HdrHistogram.UnitTests
@@ -21,7 +23,7 @@ public void ConstructorShouldRejectInvalidParameters(
2123
Assert.AreEqual(errorParamName, ex.ParamName);
2224
StringAssert.StartsWith(errorMessage, ex.Message);
2325
}
24-
26+
2527

2628
[TestCase(2, 2)]
2729
[TestCase(HighestTrackableValue, NumberOfSignificantValueDigits)]
@@ -123,6 +125,23 @@ public void RecordAction_increments_TotalCount()
123125
Assert.AreEqual(1, longHistogram.TotalCount);
124126
}
125127

128+
[Test]
129+
public void RecordAction_records_in_correct_units()
130+
{
131+
var pause = TimeSpan.FromSeconds(1);
132+
var longHistogram = Create(HighestTrackableValue, NumberOfSignificantValueDigits);
133+
134+
longHistogram.Record(() => Thread.Sleep(pause));
135+
136+
var stringWriter = new StringWriter();
137+
longHistogram.OutputPercentileDistribution(stringWriter, 5, OutputScalingFactor.TimeStampToMilliseconds, true);
138+
//First column of second row.
139+
var recordedMilliseconds = GetCellValue(stringWriter.ToString(), 0, 1);
140+
var actual = double.Parse(recordedMilliseconds);
141+
var expected = pause.TotalMilliseconds;
142+
var delta = expected * 0.1; //10% Variance to allow for slack in transitioning from Thread.Sleep
143+
Assert.AreEqual(expected, actual, delta);
144+
}
126145

127146
[Test]
128147
public void Reset_sets_counts_to_zero()
@@ -265,5 +284,10 @@ private static int GetBucketsNeededToCoverValue(int subBucketSize, long value)
265284
protected abstract int WordSize { get; }
266285
protected abstract HistogramBase Create(long highestTrackableValue, int numberOfSignificantValueDigits);
267286
protected abstract HistogramBase Create(long lowestTrackableValue, long highestTrackableValue, int numberOfSignificantValueDigits);
287+
288+
private static string GetCellValue(string csvData, int col, int row)
289+
{
290+
return csvData.Split('\n')[row].Split(',')[col];
291+
}
268292
}
269293
}

0 commit comments

Comments
 (0)