diff --git a/src/HdrHistogram.Benchmarking/Recording/Recording32BitBenchmark.cs b/src/HdrHistogram.Benchmarking/Recording/Recording32BitBenchmark.cs
index 5d26ef2..fdf65fa 100644
--- a/src/HdrHistogram.Benchmarking/Recording/Recording32BitBenchmark.cs
+++ b/src/HdrHistogram.Benchmarking/Recording/Recording32BitBenchmark.cs
@@ -20,9 +20,39 @@ public class Recording32BitBenchmark
public Recording32BitBenchmark()
{
- //Create array of +ve numbers in the 'maxBit' bit range (i.e. 32 bit or 64bit)
+ const int lowestTrackableValue = 1;
var highestTrackableValue = TimeStamp.Minutes(10);
- _testValues = Enumerable.Range(0, 32)
+ const int numberOfSignificantValueDigits = 3;
+
+ _testValues = TestValues(highestTrackableValue);
+
+ _longHistogram = new LongHistogram(highestTrackableValue, numberOfSignificantValueDigits);
+ _intHistogram = new IntHistogram(highestTrackableValue, numberOfSignificantValueDigits);
+ _shortHistogram = new ShortHistogram(highestTrackableValue, numberOfSignificantValueDigits);
+
+ _longConcurrentHistogram = new LongConcurrentHistogram(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits);
+ _intConcurrentHistogram = new IntConcurrentHistogram(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits);
+
+ _longRecorder = new Recorder(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits, (id, low, hi, sf) => new LongHistogram(id, low, hi, sf));
+ _longConcurrentRecorder = new Recorder(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits, (id, low, hi, sf) => new LongConcurrentHistogram(id, low, hi, sf));
+ _intRecorder = new Recorder(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits, (id, low, hi, sf) => new IntHistogram(id, low, hi, sf));
+ _intConcurrentRecorder = new Recorder(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits, (id, low, hi, sf) => new IntConcurrentHistogram(id, low, hi, sf));
+ _shortRecorder = new Recorder(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits, (id, low, hi, sf) => new ShortHistogram(id, low, hi, sf));
+ }
+
+ private static long[] TestValues(long highestTrackableValue)
+ {
+ //Create array of +ve numbers in the 'maxBit' bit range (i.e. 32 bit or 64bit)
+ // 32 bit values are the 89 values
+ // 1,2,3,4,5,7,8,9,15,16,17,31,32,33,63,64,65,127,128,129,255,256,257,511,512,513,1023,1024,1025,2047,2048,2049,4095,4096,4097,8191,8192,8193,
+ // 16383,16384,16385,32767,32768,32769,65535,65536,65537,131071,131072,131073,262143,262144,262145,524287,524288,524289,1048575,1048576,1048577,
+ // 2097151,2097152,2097153,4194303,4194304,4194305,8388607,8388608,8388609,16777215,16777216,16777217,33554431,33554432,33554433,
+ // 67108863,67108864,67108865,134217727,134217728,134217729,268435455,268435456,268435457,536870911,536870912,536870913,1073741823,1073741824,1073741825
+ //These value are choosen as they are the edge case values of where our bucket boundaries lie. i.e.
+ // a power of 2
+ // 1 less than a power of 2
+ // 1 more than a power of 2
+ return Enumerable.Range(0, 32)
.Select(exp => new { Value = 1L << exp, LZC = 63 - exp })
.SelectMany(x => new[]
{
@@ -34,19 +64,6 @@ public Recording32BitBenchmark()
.Where(x => x < highestTrackableValue)
.Distinct()
.ToArray();
-
- _longHistogram = new LongHistogram(highestTrackableValue, 3);
- _intHistogram = new IntHistogram(highestTrackableValue, 3);
- _shortHistogram = new ShortHistogram(highestTrackableValue, 3);
-
- _longConcurrentHistogram = new LongConcurrentHistogram(1, highestTrackableValue, 3);
- _intConcurrentHistogram = new IntConcurrentHistogram(1, highestTrackableValue, 3);
-
- _longRecorder = new Recorder(1, highestTrackableValue, 3, (id, low, hi, sf) => new LongHistogram(id, low, hi, sf));
- _longConcurrentRecorder = new Recorder(1, highestTrackableValue, 3, (id, low, hi, sf) => new LongConcurrentHistogram(id, low, hi, sf));
- _intRecorder = new Recorder(1, highestTrackableValue, 3, (id, low, hi, sf) => new IntHistogram(id, low, hi, sf));
- _intConcurrentRecorder = new Recorder(1, highestTrackableValue, 3, (id, low, hi, sf) => new IntConcurrentHistogram(id, low, hi, sf));
- _shortRecorder = new Recorder(1, highestTrackableValue, 3, (id, low, hi, sf) => new ShortHistogram(id, low, hi, sf));
}
[Benchmark(Baseline = true)]
diff --git a/src/HdrHistogram.Examples/HdrHistogram.Examples.csproj b/src/HdrHistogram.Examples/HdrHistogram.Examples.csproj
index be9f193..630b296 100644
--- a/src/HdrHistogram.Examples/HdrHistogram.Examples.csproj
+++ b/src/HdrHistogram.Examples/HdrHistogram.Examples.csproj
@@ -45,6 +45,7 @@
+
diff --git a/src/HdrHistogram.Examples/Program.cs b/src/HdrHistogram.Examples/Program.cs
index 142fb83..fd2eb11 100644
--- a/src/HdrHistogram.Examples/Program.cs
+++ b/src/HdrHistogram.Examples/Program.cs
@@ -5,7 +5,10 @@ class Program
static void Main(string[] args)
{
//SimpleHistogramExample.Run();
- RecorderExample.Run();
+ using (var example = new RecorderExample())
+ {
+ example.Run();
+ }
}
}
}
diff --git a/src/HdrHistogram.Examples/RecorderExample.cs b/src/HdrHistogram.Examples/RecorderExample.cs
index 826971f..ca501ef 100644
--- a/src/HdrHistogram.Examples/RecorderExample.cs
+++ b/src/HdrHistogram.Examples/RecorderExample.cs
@@ -1,8 +1,6 @@
using System;
using System.Diagnostics;
using System.IO;
-using System.Net;
-using System.Net.Sockets;
using System.Threading;
namespace HdrHistogram.Examples
@@ -12,82 +10,103 @@ namespace HdrHistogram.Examples
/// time it takes to perform a simple Datagram Socket create/close operation,
/// and report a histogram of the times at the end.
///
- static class RecorderExample
+ internal sealed class RecorderExample : IDisposable
{
- private static readonly Recorder Recorder = new Recorder(1, TimeStamp.Hours(1), 3, (id, low, high, sf) => new LongHistogram(id, low, high, sf));
- private static readonly Lazy AddressFamily = new Lazy(() => GetAddressFamily("google.com"));
+ private const string LogPath = "DatagramSocket.histogram.log";
private static readonly TimeSpan RunPeriod = TimeSpan.FromSeconds(10);
- private static readonly LongHistogram AccumulatingHistogram = new LongHistogram(TimeStamp.Hours(1), 3);
- private const string LogPath = "DatagramSocket.histogram.log";
- private static HistogramLogWriter _logWriter;
- private static FileStream _outputStream;
- private static int _isCompleted = 0;
- public static void Run()
- {
- Console.WriteLine($"Running for {RunPeriod.TotalSeconds}sec.");
+ private readonly HistogramLogWriter _logWriter;
+ private readonly FileStream _outputStream;
+ private int _isCompleted = -1;
+
+ public RecorderExample()
+ {
_outputStream = File.Create(LogPath);
_logWriter = new HistogramLogWriter(_outputStream);
+ }
+
+ public void Run()
+ {
+ if (HasRunBeenCalled())
+ throw new InvalidOperationException("Can only call run once.");
+
+ Console.WriteLine($"Running for {RunPeriod.TotalSeconds}sec.");
+
//Write the headers, but no histograms (as we don't have any yet).
_logWriter.Write(DateTime.Now);
- var outputThread = new Thread(ts => WriteToDisk());
- outputThread.Start();
- RecordMeasurements();
+ //ThreadSafe-writes require a Concurrent implementation of a Histogram
+ //ThreadSafe-reads require a recorder
+ var recorder = HistogramFactory
+ .With64BitBucketSize() //LongHistogram
+ .WithValuesFrom(1) //Default value
+ .WithValuesUpTo(TimeStamp.Minutes(10)) //Default value
+ .WithPrecisionOf(3) //Default value
+ .WithThreadSafeWrites() //Switches internal imp to concurrent version i.e. LongConcurrentHistogram
+ .WithThreadSafeReads() //returns a Recorder that wraps the LongConcurrentHistogram
+ .Create();
+
+ var outputThread = new Thread(ts => WriteToDisk((Recorder)ts));
+ outputThread.Start(recorder);
+
+ RecordMeasurements(recorder);
+
+ //Wait for the output thread to complete writing.
+ outputThread.Join();
+ }
+
+ private bool HasRunBeenCalled()
+ {
+ var currentValue = Interlocked.CompareExchange(ref _isCompleted, 0, -1);
+ return currentValue != -1;
}
- private static void WriteToDisk()
+ private void WriteToDisk(Recorder recorder)
{
//Sample every second until flagged as completed.
+ var accumulatingHistogram = new LongHistogram(TimeStamp.Hours(1), 3);
while (_isCompleted == 0)
{
Thread.Sleep(1000);
- var histogram = Recorder.GetIntervalHistogram();
- AccumulatingHistogram.Add(histogram);
+ var histogram = recorder.GetIntervalHistogram();
+ accumulatingHistogram.Add(histogram);
_logWriter.Append(histogram);
- Console.WriteLine($"{DateTime.Now:o} Interval.TotalCount = {histogram.TotalCount,10:G}. Accumulated.TotalCount = {AccumulatingHistogram.TotalCount,10:G}.");
+ Console.WriteLine($"{DateTime.Now:o} Interval.TotalCount = {histogram.TotalCount,10:G}. Accumulated.TotalCount = {accumulatingHistogram.TotalCount,10:G}.");
}
_logWriter.Dispose();
_outputStream.Dispose();
+
+
Console.WriteLine("Log contents");
Console.WriteLine(File.ReadAllText(LogPath));
+ Console.WriteLine();
+ Console.WriteLine("Percentile distribution (values reported in milliseconds)");
+ accumulatingHistogram.OutputPercentileDistribution(Console.Out, outputValueUnitScalingRatio: OutputScalingFactor.TimeStampToMilliseconds);
+
Console.WriteLine("Output thread finishing.");
}
///
/// Shows a sample loop where an action is executed, and the latency of each execution is recorded.
///
- private static void RecordMeasurements()
+ private void RecordMeasurements(IRecorder recorder)
{
+ var sut = new SocketTester("google.com");
+ Action actionToMeasure = sut.CreateAndCloseDatagramSocket;
var timer = Stopwatch.StartNew();
- Action actionToMeasure = CreateAndCloseDatagramSocket;
do
{
- Recorder.Record(actionToMeasure);
+ recorder.Record(actionToMeasure);
} while (timer.Elapsed < RunPeriod);
Interlocked.Increment(ref _isCompleted);
}
- private static void CreateAndCloseDatagramSocket()
- {
- try
- {
- using (var socket = new Socket(AddressFamily.Value, SocketType.Stream, ProtocolType.Tcp))
- {
- }
- }
- catch (SocketException)
- {
- }
- }
-
- private static AddressFamily GetAddressFamily(string url)
+ public void Dispose()
{
- var hostIpAddress = Dns.GetHostEntry(url).AddressList[0];
- var hostIpEndPoint = new IPEndPoint(hostIpAddress, 80);
- return hostIpEndPoint.AddressFamily;
+ _logWriter.Dispose();
+ _outputStream.Dispose();
}
}
}
\ No newline at end of file
diff --git a/src/HdrHistogram.Examples/SocketTester.cs b/src/HdrHistogram.Examples/SocketTester.cs
new file mode 100644
index 0000000..30e7340
--- /dev/null
+++ b/src/HdrHistogram.Examples/SocketTester.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Net;
+using System.Net.Sockets;
+
+namespace HdrHistogram.Examples
+{
+ ///
+ /// A class used to test opening and closing a TCP socket.
+ ///
+ public class SocketTester
+ {
+ private readonly Lazy _addressFamily;
+ public SocketTester(string url)
+ {
+ _addressFamily = new Lazy(() => GetAddressFamily(url));
+ }
+
+ public void CreateAndCloseDatagramSocket()
+ {
+ try
+ {
+ using (var socket = new Socket(_addressFamily.Value, SocketType.Stream, ProtocolType.Tcp))
+ {
+ }
+ }
+ catch (SocketException)
+ {
+ }
+ }
+
+
+ private static AddressFamily GetAddressFamily(string url)
+ {
+ var hostIpAddress = Dns.GetHostEntry(url).AddressList[0];
+ var hostIpEndPoint = new IPEndPoint(hostIpAddress, 80);
+ return hostIpEndPoint.AddressFamily;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/HdrHistogram.UnitTests/HdrHistogram.UnitTests.csproj b/src/HdrHistogram.UnitTests/HdrHistogram.UnitTests.csproj
index c36941b..265442c 100644
--- a/src/HdrHistogram.UnitTests/HdrHistogram.UnitTests.csproj
+++ b/src/HdrHistogram.UnitTests/HdrHistogram.UnitTests.csproj
@@ -51,6 +51,7 @@
+
@@ -76,7 +77,7 @@
-
+
diff --git a/src/HdrHistogram.UnitTests/HistogramFactoryTests.cs b/src/HdrHistogram.UnitTests/HistogramFactoryTests.cs
new file mode 100644
index 0000000..5bdd461
--- /dev/null
+++ b/src/HdrHistogram.UnitTests/HistogramFactoryTests.cs
@@ -0,0 +1,222 @@
+using NUnit.Framework;
+
+namespace HdrHistogram.UnitTests
+{
+ [TestFixture]
+ public class HistogramFactoryTests
+ {
+ #region 16bit recording factory tests
+
+ [Test]
+ public void CanCreateShortHistogram()
+ {
+ var actual = HistogramFactory.With16BitBucketSize()
+ .Create();
+ Assert.IsInstanceOf(actual);
+ }
+
+ [TestCase(1, 5000, 3)]
+ [TestCase(1000, 100000, 5)]
+ public void CanCreateShortHistogramWithSpecifiedRangeValues(long min, long max, int sf)
+ {
+ var actual = HistogramFactory.With16BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .Create();
+ Assert.IsInstanceOf(actual);
+ Assert.AreEqual(min, actual.LowestTrackableValue);
+ Assert.AreEqual(max, actual.HighestTrackableValue);
+ Assert.AreEqual(sf, actual.NumberOfSignificantValueDigits);
+ }
+
+ [TestCase(1, 5000, 3)]
+ [TestCase(1000, 100000, 5)]
+ public void CanCreateShortHistogramRecorder(long min, long max, int sf)
+ {
+ var actual = HistogramFactory.With16BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .WithThreadSafeReads()
+ .Create();
+ var histogram = actual.GetIntervalHistogram();
+ Assert.IsInstanceOf(histogram);
+ Assert.AreEqual(min, histogram.LowestTrackableValue);
+ Assert.AreEqual(max, histogram.HighestTrackableValue);
+ Assert.AreEqual(sf, histogram.NumberOfSignificantValueDigits);
+ }
+
+ #endregion
+
+ #region 32bit recording factory tests
+
+ [Test]
+ public void CanCreateIntHistogram()
+ {
+ var actual = HistogramFactory.With32BitBucketSize()
+ .Create();
+ Assert.IsInstanceOf(actual);
+ }
+ [Test]
+ public void CanCreateIntConcurrentHistogram()
+ {
+ var actual = HistogramFactory.With32BitBucketSize()
+ .WithThreadSafeWrites()
+ .Create();
+ Assert.IsInstanceOf(actual);
+ }
+
+ [TestCase(1, 5000, 3)]
+ [TestCase(1000, 100000, 5)]
+ public void CanCreateIntHistogramWithSpecifiedRangeValues(long min, long max, int sf)
+ {
+ var actual = HistogramFactory.With32BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .Create();
+ Assert.IsInstanceOf(actual);
+ Assert.AreEqual(min, actual.LowestTrackableValue);
+ Assert.AreEqual(max, actual.HighestTrackableValue);
+ Assert.AreEqual(sf, actual.NumberOfSignificantValueDigits);
+ }
+ [TestCase(1, 5000, 3)]
+ [TestCase(1000, 100000, 5)]
+ public void IntConcurrentHistogramWithSpecifiedRangeValues(long min, long max, int sf)
+ {
+ var actual = HistogramFactory.With32BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .WithThreadSafeWrites()
+ .Create();
+ Assert.IsInstanceOf(actual);
+ Assert.AreEqual(min, actual.LowestTrackableValue);
+ Assert.AreEqual(max, actual.HighestTrackableValue);
+ Assert.AreEqual(sf, actual.NumberOfSignificantValueDigits);
+ }
+
+ [TestCase(1, 5000, 3)]
+ [TestCase(1000, 100000, 5)]
+ public void CanCreateIntHistogramRecorder(long min, long max, int sf)
+ {
+ var actual = HistogramFactory.With32BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .WithThreadSafeReads()
+ .Create();
+ var histogram = actual.GetIntervalHistogram();
+ Assert.IsInstanceOf(histogram);
+ Assert.AreEqual(min, histogram.LowestTrackableValue);
+ Assert.AreEqual(max, histogram.HighestTrackableValue);
+ Assert.AreEqual(sf, histogram.NumberOfSignificantValueDigits);
+ }
+
+ [TestCase(1, 5000, 3)]
+ [TestCase(1000, 100000, 5)]
+ public void CanCreateIntConcurrentHistogramRecorder(long min, long max, int sf)
+ {
+ var actual = HistogramFactory.With32BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .WithThreadSafeWrites()
+ .WithThreadSafeReads()
+ .Create();
+ var histogram = actual.GetIntervalHistogram();
+ Assert.IsInstanceOf(histogram);
+ Assert.AreEqual(min, histogram.LowestTrackableValue);
+ Assert.AreEqual(max, histogram.HighestTrackableValue);
+ Assert.AreEqual(sf, histogram.NumberOfSignificantValueDigits);
+ }
+
+ #endregion
+
+ #region 64bit recording factory tests
+
+ [Test]
+ public void CanCreateLongHistogram()
+ {
+ var actual = HistogramFactory.With64BitBucketSize()
+ .Create();
+ Assert.IsInstanceOf(actual);
+ }
+ [Test]
+ public void CanCreateLongConcurrentHistogram()
+ {
+ var actual = HistogramFactory.With64BitBucketSize()
+ .WithThreadSafeWrites()
+ .Create();
+ Assert.IsInstanceOf(actual);
+ }
+
+ [TestCase(1, 5000, 3)]
+ [TestCase(1000, 100000, 5)]
+ public void CanCreateLongHistogramWithSpecifiedRangeValues(long min, long max, int sf)
+ {
+ var actual = HistogramFactory.With64BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .Create();
+ Assert.IsInstanceOf(actual);
+ Assert.AreEqual(min, actual.LowestTrackableValue);
+ Assert.AreEqual(max, actual.HighestTrackableValue);
+ Assert.AreEqual(sf, actual.NumberOfSignificantValueDigits);
+ }
+ [TestCase(1, 5000, 3)]
+ [TestCase(1000, 100000, 5)]
+ public void LongConcurrentHistogramWithSpecifiedRangeValues(long min, long max, int sf)
+ {
+ var actual = HistogramFactory.With64BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .WithThreadSafeWrites()
+ .Create();
+ Assert.IsInstanceOf(actual);
+ Assert.AreEqual(min, actual.LowestTrackableValue);
+ Assert.AreEqual(max, actual.HighestTrackableValue);
+ Assert.AreEqual(sf, actual.NumberOfSignificantValueDigits);
+ }
+
+ [TestCase(1, 5000, 3)]
+ [TestCase(1000, 100000, 5)]
+ public void CanCreateLongHistogramRecorder(long min, long max, int sf)
+ {
+ var actual = HistogramFactory.With64BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .WithThreadSafeReads()
+ .Create();
+ var histogram = actual.GetIntervalHistogram();
+ Assert.IsInstanceOf(histogram);
+ Assert.AreEqual(min, histogram.LowestTrackableValue);
+ Assert.AreEqual(max, histogram.HighestTrackableValue);
+ Assert.AreEqual(sf, histogram.NumberOfSignificantValueDigits);
+ }
+
+ [TestCase(1, 5000, 3)]
+ [TestCase(1000, 100000, 5)]
+ public void CanCreateLongConcurrentHistogramRecorder(long min, long max, int sf)
+ {
+ var actual = HistogramFactory.With64BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .WithThreadSafeWrites()
+ .WithThreadSafeReads()
+ .Create();
+ var histogram = actual.GetIntervalHistogram();
+ Assert.IsInstanceOf(histogram);
+ Assert.AreEqual(min, histogram.LowestTrackableValue);
+ Assert.AreEqual(max, histogram.HighestTrackableValue);
+ Assert.AreEqual(sf, histogram.NumberOfSignificantValueDigits);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/HdrHistogram.UnitTests/HistogramTestBase.cs b/src/HdrHistogram.UnitTests/HistogramTestBase.cs
index ae0055f..b3f8d41 100644
--- a/src/HdrHistogram.UnitTests/HistogramTestBase.cs
+++ b/src/HdrHistogram.UnitTests/HistogramTestBase.cs
@@ -22,6 +22,10 @@ public abstract class HistogramTestBase
{ 8, (low,high,sf) => new LongHistogram(low, high, sf) }
};
+ protected abstract int WordSize { get; }
+ protected abstract HistogramBase Create(long highestTrackableValue, int numberOfSignificantValueDigits);
+ protected abstract HistogramBase Create(long lowestTrackableValue, long highestTrackableValue, int numberOfSignificantValueDigits);
+
[TestCase(0, 1, DefaultSignificantFigures, "lowestTrackableValue", "lowestTrackableValue must be >= 1")]
[TestCase(DefautltLowestDiscernibleValue, 1, DefaultSignificantFigures, "highestTrackableValue", "highestTrackableValue must be >= 2 * lowestTrackableValue")]
[TestCase(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, 6, "numberOfSignificantValueDigits", "numberOfSignificantValueDigits must be between 0 and 5")]
@@ -40,26 +44,26 @@ public void ConstructorShouldRejectInvalidParameters(
[TestCase(DefaultHighestTrackableValue, DefaultSignificantFigures)]
public void TestConstructionArgumentGets(long highestTrackableValue, int numberOfSignificantValueDigits)
{
- var longHistogram = Create(highestTrackableValue, numberOfSignificantValueDigits);
- Assert.AreEqual(1, longHistogram.LowestTrackableValue);
- Assert.AreEqual(highestTrackableValue, longHistogram.HighestTrackableValue);
- Assert.AreEqual(numberOfSignificantValueDigits, longHistogram.NumberOfSignificantValueDigits);
+ var histogram = Create(highestTrackableValue, numberOfSignificantValueDigits);
+ Assert.AreEqual(1, histogram.LowestTrackableValue);
+ Assert.AreEqual(highestTrackableValue, histogram.HighestTrackableValue);
+ Assert.AreEqual(numberOfSignificantValueDigits, histogram.NumberOfSignificantValueDigits);
}
[TestCase(1, 2, 2)]
[TestCase(10, DefaultHighestTrackableValue, DefaultSignificantFigures)]
public void TestConstructionArgumentGets(long lowestTrackableValue, long highestTrackableValue, int numberOfSignificantValueDigits)
{
- var longHistogram = Create(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits);
- Assert.AreEqual(lowestTrackableValue, longHistogram.LowestTrackableValue);
- Assert.AreEqual(highestTrackableValue, longHistogram.HighestTrackableValue);
- Assert.AreEqual(numberOfSignificantValueDigits, longHistogram.NumberOfSignificantValueDigits);
+ var histogram = Create(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits);
+ Assert.AreEqual(lowestTrackableValue, histogram.LowestTrackableValue);
+ Assert.AreEqual(highestTrackableValue, histogram.HighestTrackableValue);
+ Assert.AreEqual(numberOfSignificantValueDigits, histogram.NumberOfSignificantValueDigits);
}
[Test]
public void TestGetEstimatedFootprintInBytes2()
{
- var longHistogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
+ var histogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
var largestValueWithSingleUnitResolution = 2 * (long)Math.Pow(10, DefaultSignificantFigures);
var subBucketCountMagnitude = (int)Math.Ceiling(Math.Log(largestValueWithSingleUnitResolution) / Math.Log(2));
var subBucketSize = (int)Math.Pow(2, (subBucketCountMagnitude));
@@ -70,37 +74,37 @@ public void TestGetEstimatedFootprintInBytes2()
var length = (bucketCount + 1) * (subBucketSize / 2);
var expectedSize = header + (width * length);
- Assert.AreEqual(expectedSize, longHistogram.GetEstimatedFootprintInBytes());
+ Assert.AreEqual(expectedSize, histogram.GetEstimatedFootprintInBytes());
}
[Test]
public void RecordValue_increments_TotalCount()
{
- var longHistogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
+ var histogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
for (int i = 1; i < 5; i++)
{
- longHistogram.RecordValue(i);
- Assert.AreEqual(i, longHistogram.TotalCount);
+ histogram.RecordValue(i);
+ Assert.AreEqual(i, histogram.TotalCount);
}
}
[Test]
public void RecordValue_increments_CountAtValue()
{
- var longHistogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
+ var histogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
for (int i = 1; i < 5; i++)
{
- longHistogram.RecordValue(TestValueLevel);
- Assert.AreEqual(i, longHistogram.GetCountAtValue(TestValueLevel));
+ histogram.RecordValue(TestValueLevel);
+ Assert.AreEqual(i, histogram.GetCountAtValue(TestValueLevel));
}
}
[Test]
public void RecordValue_Overflow_ShouldThrowException()
{
- var longHistogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
- Assert.Throws(() => longHistogram.RecordValue(DefaultHighestTrackableValue * 3));
+ var histogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
+ Assert.Throws(() => histogram.RecordValue(DefaultHighestTrackableValue * 3));
}
[TestCase(5)]
@@ -161,22 +165,22 @@ public void RecordValueWithExpectedInterval()
[Test]
public void RecordAction_increments_TotalCount()
{
- var longHistogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
+ var histogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
- longHistogram.Record(() => { });
- Assert.AreEqual(1, longHistogram.TotalCount);
+ histogram.Record(() => { });
+ Assert.AreEqual(1, histogram.TotalCount);
}
[Test]
public void RecordAction_records_in_correct_units()
{
var pause = TimeSpan.FromSeconds(1);
- var longHistogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
+ var histogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
- longHistogram.Record(() => Thread.Sleep(pause));
+ histogram.Record(() => Thread.Sleep(pause));
var stringWriter = new StringWriter();
- longHistogram.OutputPercentileDistribution(stringWriter,
+ histogram.OutputPercentileDistribution(stringWriter,
percentileTicksPerHalfDistance: 5,
outputValueUnitScalingRatio: OutputScalingFactor.TimeStampToMilliseconds,
useCsvFormat: true);
@@ -192,47 +196,47 @@ public void RecordAction_records_in_correct_units()
[Test]
public void Reset_sets_counts_to_zero()
{
- var longHistogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
- longHistogram.RecordValue(TestValueLevel);
+ var histogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
+ histogram.RecordValue(TestValueLevel);
- longHistogram.Reset();
+ histogram.Reset();
- Assert.AreEqual(0L, longHistogram.GetCountAtValue(TestValueLevel));
- Assert.AreEqual(0L, longHistogram.TotalCount);
+ Assert.AreEqual(0L, histogram.GetCountAtValue(TestValueLevel));
+ Assert.AreEqual(0L, histogram.TotalCount);
}
[Test]
public void Add_should_sum_the_counts_from_two_histograms()
{
- var longHistogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
+ var histogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
var other = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
- longHistogram.RecordValue(TestValueLevel);
- longHistogram.RecordValue(TestValueLevel * 1000);
+ histogram.RecordValue(TestValueLevel);
+ histogram.RecordValue(TestValueLevel * 1000);
other.RecordValue(TestValueLevel);
other.RecordValue(TestValueLevel * 1000);
- longHistogram.Add(other);
+ histogram.Add(other);
- Assert.AreEqual(2L, longHistogram.GetCountAtValue(TestValueLevel));
- Assert.AreEqual(2L, longHistogram.GetCountAtValue(TestValueLevel * 1000));
- Assert.AreEqual(4L, longHistogram.TotalCount);
+ Assert.AreEqual(2L, histogram.GetCountAtValue(TestValueLevel));
+ Assert.AreEqual(2L, histogram.GetCountAtValue(TestValueLevel * 1000));
+ Assert.AreEqual(4L, histogram.TotalCount);
}
[Test]
public void Add_should_allow_small_range_hsitograms_to_be_added()
{
- var longHistogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
+ var histogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
- longHistogram.RecordValue(TestValueLevel);
- longHistogram.RecordValue(TestValueLevel * 1000);
+ histogram.RecordValue(TestValueLevel);
+ histogram.RecordValue(TestValueLevel * 1000);
var biggerOther = Create(DefaultHighestTrackableValue * 2, DefaultSignificantFigures);
biggerOther.RecordValue(TestValueLevel);
biggerOther.RecordValue(TestValueLevel * 1000);
// Adding the smaller histogram to the bigger one should work:
- biggerOther.Add(longHistogram);
+ biggerOther.Add(histogram);
Assert.AreEqual(2L, biggerOther.GetCountAtValue(TestValueLevel));
Assert.AreEqual(2L, biggerOther.GetCountAtValue(TestValueLevel * 1000));
Assert.AreEqual(4L, biggerOther.TotalCount);
@@ -241,10 +245,10 @@ public void Add_should_allow_small_range_hsitograms_to_be_added()
[Test]
public void Add_throws_if_other_has_a_larger_range()
{
- var longHistogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
+ var histogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
var biggerOther = Create(DefaultHighestTrackableValue * 2, DefaultSignificantFigures);
- Assert.Throws(() => { longHistogram.Add(biggerOther); });
+ Assert.Throws(() => { histogram.Add(biggerOther); });
}
[TestCase(1, 1)]
@@ -254,8 +258,8 @@ public void Add_throws_if_other_has_a_larger_range()
[TestCase(8, 10000)]
public void SizeOfEquivalentValueRangeForValue(int expected, int value)
{
- var longHistogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
- Assert.AreEqual(expected, longHistogram.SizeOfEquivalentValueRange(value));
+ var histogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
+ Assert.AreEqual(expected, histogram.SizeOfEquivalentValueRange(value));
//Validate the scaling too.
var scaledHistogram = Create(1024, DefaultHighestTrackableValue, DefaultSignificantFigures);
@@ -266,8 +270,8 @@ public void SizeOfEquivalentValueRangeForValue(int expected, int value)
[TestCase(10008, 10009)]
public void LowestEquivalentValue_returns_the_smallest_value_that_would_be_assigned_to_the_same_count(int expected, int value)
{
- var longHistogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
- Assert.AreEqual(expected, longHistogram.LowestEquivalentValue(value));
+ var histogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
+ Assert.AreEqual(expected, histogram.LowestEquivalentValue(value));
//Validate the scaling too
var scaledHistogram = Create(1024, DefaultHighestTrackableValue, DefaultSignificantFigures);
Assert.AreEqual(expected * 1024, scaledHistogram.LowestEquivalentValue(value * 1024));
@@ -281,8 +285,8 @@ public void LowestEquivalentValue_returns_the_smallest_value_that_would_be_assig
[TestCase(10015, 10008)]
public void HighestEquivalentValue_returns_the_smallest_value_that_would_be_assigned_to_the_same_count(int expected, int value)
{
- var longHistogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
- Assert.AreEqual(expected, longHistogram.HighestEquivalentValue(value));
+ var histogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
+ Assert.AreEqual(expected, histogram.HighestEquivalentValue(value));
//Validate the scaling too
var scaledHistogram = Create(1024, DefaultHighestTrackableValue, DefaultSignificantFigures);
Assert.AreEqual(expected * 1024 + 1023, scaledHistogram.HighestEquivalentValue(value * 1024));
@@ -295,8 +299,8 @@ public void HighestEquivalentValue_returns_the_smallest_value_that_would_be_assi
[TestCase(10004, 10007, 0)]
public void TestMedianEquivalentValue(int expected, int value, int scaledHeader)
{
- var longHistogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
- Assert.AreEqual(expected, longHistogram.MedianEquivalentValue(value));
+ var histogram = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
+ Assert.AreEqual(expected, histogram.MedianEquivalentValue(value));
//Validate the scaling too
var scaledHistogram = Create(1024, DefaultHighestTrackableValue, DefaultSignificantFigures);
Assert.AreEqual(expected * 1024 + scaledHeader, scaledHistogram.MedianEquivalentValue(value * 1024));
@@ -355,9 +359,6 @@ private static int GetBucketsNeededToCoverValue(int subBucketSize, long value)
}
return bucketsNeeded;
}
- protected abstract int WordSize { get; }
- protected abstract HistogramBase Create(long highestTrackableValue, int numberOfSignificantValueDigits);
- protected abstract HistogramBase Create(long lowestTrackableValue, long highestTrackableValue, int numberOfSignificantValueDigits);
private static string GetCellValue(string csvData, int col, int row)
{
diff --git a/src/HdrHistogram.UnitTests/IntConcurrentHistogramTests.cs b/src/HdrHistogram.UnitTests/IntConcurrentHistogramTests.cs
index 10c7874..e06fd40 100644
--- a/src/HdrHistogram.UnitTests/IntConcurrentHistogramTests.cs
+++ b/src/HdrHistogram.UnitTests/IntConcurrentHistogramTests.cs
@@ -9,12 +9,23 @@ public class IntConcurrentHistogramTests : ConcurrentHistogramTestBase
protected override HistogramBase Create(long highestTrackableValue, int numberOfSignificantValueDigits)
{
- return new IntConcurrentHistogram(1, highestTrackableValue, numberOfSignificantValueDigits);
+ //return new IntConcurrentHistogram(1, highestTrackableValue, numberOfSignificantValueDigits);
+ return HistogramFactory.With32BitBucketSize()
+ .WithValuesUpTo(highestTrackableValue)
+ .WithPrecisionOf(numberOfSignificantValueDigits)
+ .WithThreadSafeWrites()
+ .Create();
}
protected override HistogramBase Create(long lowestTrackableValue, long highestTrackableValue, int numberOfSignificantValueDigits)
{
- return new IntConcurrentHistogram(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits);
+ //return new IntConcurrentHistogram(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits);
+ return HistogramFactory.With32BitBucketSize()
+ .WithValuesFrom(lowestTrackableValue)
+ .WithValuesUpTo(highestTrackableValue)
+ .WithPrecisionOf(numberOfSignificantValueDigits)
+ .WithThreadSafeWrites()
+ .Create();
}
}
}
\ No newline at end of file
diff --git a/src/HdrHistogram.UnitTests/IntHistogramEncodingTests.cs b/src/HdrHistogram.UnitTests/IntHistogramEncodingTests.cs
index bb1181f..9df7cac 100644
--- a/src/HdrHistogram.UnitTests/IntHistogramEncodingTests.cs
+++ b/src/HdrHistogram.UnitTests/IntHistogramEncodingTests.cs
@@ -7,7 +7,11 @@ public sealed class IntHistogramEncodingTests : HistogramEncodingTestBase
{
protected override HistogramBase Create(long highestTrackableValue, int numberOfSignificantDigits)
{
- return new IntHistogram(highestTrackableValue, numberOfSignificantDigits);
+ //return new IntHistogram(highestTrackableValue, numberOfSignificantDigits);
+ return HistogramFactory.With32BitBucketSize()
+ .WithValuesUpTo(highestTrackableValue)
+ .WithPrecisionOf(numberOfSignificantDigits)
+ .Create();
}
}
}
\ No newline at end of file
diff --git a/src/HdrHistogram.UnitTests/IntHistogramTests.cs b/src/HdrHistogram.UnitTests/IntHistogramTests.cs
index 1cc07eb..5ebce48 100644
--- a/src/HdrHistogram.UnitTests/IntHistogramTests.cs
+++ b/src/HdrHistogram.UnitTests/IntHistogramTests.cs
@@ -9,12 +9,21 @@ public class IntHistogramTests : HistogramTestBase
protected override HistogramBase Create(long highestTrackableValue, int numberOfSignificantValueDigits)
{
- return new IntHistogram(highestTrackableValue, numberOfSignificantValueDigits);
+ //return new IntHistogram(highestTrackableValue, numberOfSignificantValueDigits);
+ return HistogramFactory.With32BitBucketSize()
+ .WithValuesUpTo(highestTrackableValue)
+ .WithPrecisionOf(numberOfSignificantValueDigits)
+ .Create();
}
protected override HistogramBase Create(long lowestTrackableValue, long highestTrackableValue, int numberOfSignificantValueDigits)
{
- return new IntHistogram(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits);
+ //return new IntHistogram(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits);
+ return HistogramFactory.With32BitBucketSize()
+ .WithValuesFrom(lowestTrackableValue)
+ .WithValuesUpTo(highestTrackableValue)
+ .WithPrecisionOf(numberOfSignificantValueDigits)
+ .Create();
}
}
}
\ No newline at end of file
diff --git a/src/HdrHistogram.UnitTests/LongConcurrentHistogramTests.cs b/src/HdrHistogram.UnitTests/LongConcurrentHistogramTests.cs
index 13544c4..d43cbf4 100644
--- a/src/HdrHistogram.UnitTests/LongConcurrentHistogramTests.cs
+++ b/src/HdrHistogram.UnitTests/LongConcurrentHistogramTests.cs
@@ -9,12 +9,23 @@ public class LongConcurrentHistogramTests : ConcurrentHistogramTestBase
protected override HistogramBase Create(long highestTrackableValue, int numberOfSignificantValueDigits)
{
- return new LongConcurrentHistogram(1, highestTrackableValue, numberOfSignificantValueDigits);
+ //return new LongConcurrentHistogram(1, highestTrackableValue, numberOfSignificantValueDigits);
+ return HistogramFactory.With64BitBucketSize()
+ .WithValuesUpTo(highestTrackableValue)
+ .WithPrecisionOf(numberOfSignificantValueDigits)
+ .WithThreadSafeWrites()
+ .Create();
}
protected override HistogramBase Create(long lowestTrackableValue, long highestTrackableValue, int numberOfSignificantValueDigits)
{
- return new LongConcurrentHistogram(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits);
+ //return new LongConcurrentHistogram(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits);
+ return HistogramFactory.With64BitBucketSize()
+ .WithValuesFrom(lowestTrackableValue)
+ .WithValuesUpTo(highestTrackableValue)
+ .WithPrecisionOf(numberOfSignificantValueDigits)
+ .WithThreadSafeWrites()
+ .Create();
}
}
}
\ No newline at end of file
diff --git a/src/HdrHistogram.UnitTests/LongHistogramEncodingTests.cs b/src/HdrHistogram.UnitTests/LongHistogramEncodingTests.cs
index ab5a420..fd801cd 100644
--- a/src/HdrHistogram.UnitTests/LongHistogramEncodingTests.cs
+++ b/src/HdrHistogram.UnitTests/LongHistogramEncodingTests.cs
@@ -7,7 +7,11 @@ public sealed class LongHistogramEncodingTests : HistogramEncodingTestBase
{
protected override HistogramBase Create(long highestTrackableValue, int numberOfSignificantDigits)
{
- return new LongHistogram(highestTrackableValue, numberOfSignificantDigits);
+ //return new LongHistogram(highestTrackableValue, numberOfSignificantDigits);
+ return HistogramFactory.With64BitBucketSize()
+ .WithValuesUpTo(highestTrackableValue)
+ .WithPrecisionOf(numberOfSignificantDigits)
+ .Create();
}
}
}
diff --git a/src/HdrHistogram.UnitTests/LongHistogramTests.cs b/src/HdrHistogram.UnitTests/LongHistogramTests.cs
index 0db6517..bdd5937 100644
--- a/src/HdrHistogram.UnitTests/LongHistogramTests.cs
+++ b/src/HdrHistogram.UnitTests/LongHistogramTests.cs
@@ -8,11 +8,20 @@ public class LongHistogramTests : HistogramTestBase
protected override int WordSize => sizeof(long);
protected override HistogramBase Create(long highestTrackableValue, int numberOfSignificantValueDigits)
{
- return new LongHistogram(highestTrackableValue, numberOfSignificantValueDigits);
+ //return new LongHistogram(highestTrackableValue, numberOfSignificantValueDigits);
+ return HistogramFactory.With64BitBucketSize()
+ .WithValuesUpTo(highestTrackableValue)
+ .WithPrecisionOf(numberOfSignificantValueDigits)
+ .Create();
}
protected override HistogramBase Create(long lowestTrackableValue, long highestTrackableValue, int numberOfSignificantValueDigits)
{
- return new LongHistogram(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits);
+ //return new LongHistogram(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits);
+ return HistogramFactory.With64BitBucketSize()
+ .WithValuesFrom(lowestTrackableValue)
+ .WithValuesUpTo(highestTrackableValue)
+ .WithPrecisionOf(numberOfSignificantValueDigits)
+ .Create();
}
}
}
diff --git a/src/HdrHistogram.UnitTests/Recording/RecorderTestWithIntConcurrentHistogram.cs b/src/HdrHistogram.UnitTests/Recording/RecorderTestWithIntConcurrentHistogram.cs
index 9906b58..c4e12ad 100644
--- a/src/HdrHistogram.UnitTests/Recording/RecorderTestWithIntConcurrentHistogram.cs
+++ b/src/HdrHistogram.UnitTests/Recording/RecorderTestWithIntConcurrentHistogram.cs
@@ -5,9 +5,26 @@ namespace HdrHistogram.UnitTests.Recording
[TestFixture]
public sealed class RecorderTestWithIntConcurrentHistogram : RecorderTestsBase
{
- protected override HistogramBase Create(long id, long min, long max, int sf)
+ protected override HistogramBase CreateHistogram(long id, long min, long max, int sf)
{
- return new IntConcurrentHistogram(id, min, max, sf);
+ //return new IntConcurrentHistogram(id, min, max, sf);
+ return HistogramFactory.With32BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .WithThreadSafeWrites()
+ .Create();
+ }
+
+ protected override Recorder Create(long min, long max, int sf)
+ {
+ return HistogramFactory.With32BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .WithThreadSafeWrites()
+ .WithThreadSafeReads()
+ .Create();
}
}
}
\ No newline at end of file
diff --git a/src/HdrHistogram.UnitTests/Recording/RecorderTestWithIntHistogram.cs b/src/HdrHistogram.UnitTests/Recording/RecorderTestWithIntHistogram.cs
index bf76b3a..8971a0f 100644
--- a/src/HdrHistogram.UnitTests/Recording/RecorderTestWithIntHistogram.cs
+++ b/src/HdrHistogram.UnitTests/Recording/RecorderTestWithIntHistogram.cs
@@ -5,9 +5,24 @@ namespace HdrHistogram.UnitTests.Recording
[TestFixture]
public sealed class RecorderTestWithIntHistogram : RecorderTestsBase
{
- protected override HistogramBase Create(long id, long min, long max, int sf)
+ protected override HistogramBase CreateHistogram(long id, long min, long max, int sf)
{
- return new IntHistogram(id, min, max, sf);
+ //return new IntHistogram(id, min, max, sf);
+ return HistogramFactory.With32BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .Create();
+ }
+
+ protected override Recorder Create(long min, long max, int sf)
+ {
+ return HistogramFactory.With32BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .WithThreadSafeReads()
+ .Create();
}
}
}
\ No newline at end of file
diff --git a/src/HdrHistogram.UnitTests/Recording/RecorderTestWithLShortHistogram.cs b/src/HdrHistogram.UnitTests/Recording/RecorderTestWithLShortHistogram.cs
deleted file mode 100644
index 56e2964..0000000
--- a/src/HdrHistogram.UnitTests/Recording/RecorderTestWithLShortHistogram.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using NUnit.Framework;
-
-namespace HdrHistogram.UnitTests.Recording
-{
- [TestFixture]
- public sealed class RecorderTestWithLShortHistogram : RecorderTestsBase
- {
- protected override HistogramBase Create(long id, long min, long max, int sf)
- {
- return new ShortHistogram(id, min, max, sf);
- }
- }
-}
\ No newline at end of file
diff --git a/src/HdrHistogram.UnitTests/Recording/RecorderTestWithLongConcurrentHistogram.cs b/src/HdrHistogram.UnitTests/Recording/RecorderTestWithLongConcurrentHistogram.cs
index b0e5b89..4b23a28 100644
--- a/src/HdrHistogram.UnitTests/Recording/RecorderTestWithLongConcurrentHistogram.cs
+++ b/src/HdrHistogram.UnitTests/Recording/RecorderTestWithLongConcurrentHistogram.cs
@@ -5,9 +5,25 @@ namespace HdrHistogram.UnitTests.Recording
[TestFixture]
public sealed class RecorderTestWithLongConcurrentHistogram : RecorderTestsBase
{
- protected override HistogramBase Create(long id, long min, long max, int sf)
+ protected override HistogramBase CreateHistogram(long id, long min, long max, int sf)
{
- return new LongConcurrentHistogram(id, min, max, sf);
+ return HistogramFactory.With64BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .WithThreadSafeWrites()
+ .Create();
+ }
+
+ protected override Recorder Create(long min, long max, int sf)
+ {
+ return HistogramFactory.With64BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .WithThreadSafeWrites()
+ .WithThreadSafeReads()
+ .Create();
}
}
}
\ No newline at end of file
diff --git a/src/HdrHistogram.UnitTests/Recording/RecorderTestWithLongHistogram.cs b/src/HdrHistogram.UnitTests/Recording/RecorderTestWithLongHistogram.cs
index 3928fdb..57a26e4 100644
--- a/src/HdrHistogram.UnitTests/Recording/RecorderTestWithLongHistogram.cs
+++ b/src/HdrHistogram.UnitTests/Recording/RecorderTestWithLongHistogram.cs
@@ -5,9 +5,24 @@ namespace HdrHistogram.UnitTests.Recording
[TestFixture]
public sealed class RecorderTestWithLongHistogram : RecorderTestsBase
{
- protected override HistogramBase Create(long id, long min, long max, int sf)
+ protected override HistogramBase CreateHistogram(long id, long min, long max, int sf)
{
- return new LongHistogram(id, min, max, sf);
+ //return new LongHistogram(id, min, max, sf);
+ return HistogramFactory.With64BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .Create();
+ }
+
+ protected override Recorder Create(long min, long max, int sf)
+ {
+ return HistogramFactory.With64BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .WithThreadSafeReads()
+ .Create();
}
}
}
\ No newline at end of file
diff --git a/src/HdrHistogram.UnitTests/Recording/RecorderTestWithShortHistogram.cs b/src/HdrHistogram.UnitTests/Recording/RecorderTestWithShortHistogram.cs
new file mode 100644
index 0000000..ae83a28
--- /dev/null
+++ b/src/HdrHistogram.UnitTests/Recording/RecorderTestWithShortHistogram.cs
@@ -0,0 +1,28 @@
+using NUnit.Framework;
+
+namespace HdrHistogram.UnitTests.Recording
+{
+ [TestFixture]
+ public sealed class RecorderTestWithShortHistogram : RecorderTestsBase
+ {
+ protected override HistogramBase CreateHistogram(long id, long min, long max, int sf)
+ {
+ //return new ShortHistogram(id, min, max, sf);
+ return HistogramFactory.With16BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .Create();
+ }
+
+ protected override Recorder Create(long min, long max, int sf)
+ {
+ return HistogramFactory.With16BitBucketSize()
+ .WithValuesFrom(min)
+ .WithValuesUpTo(max)
+ .WithPrecisionOf(sf)
+ .WithThreadSafeReads()
+ .Create();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/HdrHistogram.UnitTests/Recording/RecorderTestsBase.cs b/src/HdrHistogram.UnitTests/Recording/RecorderTestsBase.cs
index 660f56c..17e6c97 100644
--- a/src/HdrHistogram.UnitTests/Recording/RecorderTestsBase.cs
+++ b/src/HdrHistogram.UnitTests/Recording/RecorderTestsBase.cs
@@ -10,7 +10,8 @@ public abstract class RecorderTestsBase
private const long DefaultHighestTrackableValue = 7716549600;//TimeStamp.Hours(1); // e.g. for 1 hr in system clock ticks (StopWatch.Frequency)
private const int DefaultSignificantFigures = 3;
- protected abstract HistogramBase Create(long id, long min, long max, int sf);
+ protected abstract HistogramBase CreateHistogram(long id, long min, long max, int sf);
+ protected abstract Recorder Create(long min, long max, int sf);
[TestCase(0, 1, DefaultSignificantFigures, "lowestTrackableValue", "lowestTrackableValue must be >= 1")]
[TestCase(1, 1, DefaultSignificantFigures, "highestTrackableValue", "highestTrackableValue must be >= 2 * lowestTrackableValue")]
@@ -21,11 +22,9 @@ public void ConstructorShouldRejectInvalidParameters(
string errorParamName, string errorMessage)
{
var ex = Assert.Throws(() =>
- new Recorder(
- lowestTrackableValue,
+ Create(lowestTrackableValue,
highestTrackableValue,
- numberOfSignificantValueDigits,
- Create));
+ numberOfSignificantValueDigits));
Assert.AreEqual(errorParamName, ex.ParamName);
StringAssert.StartsWith(errorMessage, ex.Message);
}
@@ -33,7 +32,7 @@ public void ConstructorShouldRejectInvalidParameters(
[Test]
public void GetIntervalHistogram_returns_alternating_instances_from_factory()
{
- var recorder = new Recorder(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures, Create);
+ var recorder = Create(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures);
var a = recorder.GetIntervalHistogram();
var b = recorder.GetIntervalHistogram(a);
var c = recorder.GetIntervalHistogram(b);
@@ -48,7 +47,7 @@ public void GetIntervalHistogram_returns_alternating_instances_from_factory()
[Test]
public void GetIntervalHistogram_returns_current_histogram_values()
{
- var recorder = new Recorder(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures, Create);
+ var recorder = Create(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures);
recorder.RecordValue(1);
recorder.RecordValue(10);
recorder.RecordValue(100);
@@ -61,7 +60,7 @@ public void GetIntervalHistogram_returns_current_histogram_values()
[Test]
public void GetIntervalHistogram_causes_recording_to_happen_on_new_histogram()
{
- var recorder = new Recorder(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures, Create);
+ var recorder = Create(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures);
recorder.RecordValue(1);
var histogramPrimary = recorder.GetIntervalHistogram();
Assert.AreEqual(1, histogramPrimary.GetCountAtValue(1));
@@ -78,7 +77,7 @@ public void GetIntervalHistogram_causes_recording_to_happen_on_new_histogram()
[Test]
public void GetIntervalHistogram_resets_recycled_histogram()
{
- var recorder = new Recorder(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures, Create);
+ var recorder = Create(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures);
recorder.RecordValue(1);
recorder.RecordValue(10);
recorder.RecordValue(100);
@@ -100,7 +99,7 @@ public void GetIntervalHistogram_resets_recycled_histogram()
[Test]
public void RecordValue_increments_TotalCount()
{
- var recorder = new Recorder(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures, Create);
+ var recorder = Create(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures);
recorder.RecordValue(1000);
var histogram = recorder.GetIntervalHistogram();
Assert.AreEqual(1, histogram.TotalCount);
@@ -109,7 +108,7 @@ public void RecordValue_increments_TotalCount()
[Test]
public void RecordValue_increments_CountAtValue()
{
- var recorder = new Recorder(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures, Create);
+ var recorder = Create(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures);
recorder.RecordValue(1000);
recorder.RecordValue(1000);
recorder.RecordValue(1000);
@@ -121,14 +120,14 @@ public void RecordValue_increments_CountAtValue()
public void RecordValue_Overflow_ShouldThrowException()
{
var highestTrackableValue = DefaultHighestTrackableValue;
- var recorder = new Recorder(DefautltLowestDiscernibleValue, highestTrackableValue, DefaultSignificantFigures, Create);
+ var recorder = Create(DefautltLowestDiscernibleValue, highestTrackableValue, DefaultSignificantFigures);
Assert.Throws(() => recorder.RecordValue(highestTrackableValue * 3));
}
[Test]
public void RecordValueWithCount_increments_TotalCount()
{
- var recorder = new Recorder(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures, Create);
+ var recorder = Create(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures);
recorder.RecordValueWithCount(1000, 10);
var histogram = recorder.GetIntervalHistogram();
Assert.AreEqual(10, histogram.TotalCount);
@@ -137,7 +136,7 @@ public void RecordValueWithCount_increments_TotalCount()
[Test]
public void RecordValueWithCount_increments_CountAtValue()
{
- var recorder = new Recorder(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures, Create);
+ var recorder = Create(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures);
recorder.RecordValueWithCount(1000, 10);
recorder.RecordValueWithCount(1000, 10);
recorder.RecordValueWithCount(5000, 20);
@@ -150,7 +149,7 @@ public void RecordValueWithCount_increments_CountAtValue()
public void RecordValueWithCount_Overflow_ShouldThrowException()
{
var highestTrackableValue = DefaultHighestTrackableValue;
- var recorder = new Recorder(DefautltLowestDiscernibleValue, highestTrackableValue, DefaultSignificantFigures, Create);
+ var recorder = Create(DefautltLowestDiscernibleValue, highestTrackableValue, DefaultSignificantFigures);
Assert.Throws(() => recorder.RecordValueWithCount(highestTrackableValue * 3, 100));
}
@@ -158,7 +157,7 @@ public void RecordValueWithCount_Overflow_ShouldThrowException()
public void RecordValueWithExpectedInterval()
{
var TestValueLevel = 4L;
- var recorder = new Recorder(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures, Create);
+ var recorder = Create(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures);
var valueHistogram = new LongHistogram(DefaultHighestTrackableValue, DefaultSignificantFigures);
recorder.RecordValueWithExpectedInterval(TestValueLevel, TestValueLevel / 4);
@@ -182,7 +181,7 @@ public void RecordValueWithExpectedInterval()
[Test]
public void RecordAction_increments_TotalCount()
{
- var recorder = new Recorder(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures, Create);
+ var recorder = Create(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures);
recorder.Record(() => { });
@@ -193,7 +192,7 @@ public void RecordAction_increments_TotalCount()
[Test]
public void Reset_clears_counts_for_instances()
{
- var recorder = new Recorder(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures, Create);
+ var recorder = Create(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures);
recorder.RecordValue(1);
recorder.RecordValue(10);
recorder.RecordValue(100);
@@ -229,7 +228,7 @@ public void GetIntervalHistogramInto_copies_data_over_provided_Histogram()
Assert.AreEqual(1, targetHistogram.GetCountAtValue(10));
Assert.AreEqual(1, targetHistogram.GetCountAtValue(100));
- var recorder = new Recorder(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures, Create);
+ var recorder = Create(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures);
recorder.RecordValue(1000);
recorder.RecordValue(10000);
recorder.RecordValue(100000);
@@ -251,8 +250,8 @@ public void GetIntervalHistogramInto_copies_data_over_provided_Histogram()
public void Using_external_histogram_for_recycling_throws()
{
const int id = -1000;
- var externallyCreatedHistogram = Create(id, DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures);
- var recorder = new Recorder(1, DefaultHighestTrackableValue, DefaultSignificantFigures, Create);
+ var externallyCreatedHistogram = CreateHistogram(id, DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures);
+ var recorder = Create(1, DefaultHighestTrackableValue, DefaultSignificantFigures);
recorder.RecordValue(1000);
Assert.Throws(() => recorder.GetIntervalHistogram(externallyCreatedHistogram));
diff --git a/src/HdrHistogram.UnitTests/ShortHistogramEncodingTests.cs b/src/HdrHistogram.UnitTests/ShortHistogramEncodingTests.cs
index e0b067d..d7f5c4a 100644
--- a/src/HdrHistogram.UnitTests/ShortHistogramEncodingTests.cs
+++ b/src/HdrHistogram.UnitTests/ShortHistogramEncodingTests.cs
@@ -7,7 +7,11 @@ public sealed class ShortHistogramEncodingTests : HistogramEncodingTestBase
{
protected override HistogramBase Create(long highestTrackableValue, int numberOfSignificantDigits)
{
- return new ShortHistogram(highestTrackableValue, numberOfSignificantDigits);
+ //return new ShortHistogram(highestTrackableValue, numberOfSignificantDigits);
+ return HistogramFactory.With16BitBucketSize()
+ .WithValuesUpTo(highestTrackableValue)
+ .WithPrecisionOf(numberOfSignificantDigits)
+ .Create();
}
protected override void LoadFullRange(IRecorder source)
@@ -19,4 +23,4 @@ protected override void LoadFullRange(IRecorder source)
source.RecordValue(DefaultHighestTrackableValue);
}
}
-}
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/HdrHistogram.UnitTests/ShortHistogramTests.cs b/src/HdrHistogram.UnitTests/ShortHistogramTests.cs
index 9f75eb5..b1e63c4 100644
--- a/src/HdrHistogram.UnitTests/ShortHistogramTests.cs
+++ b/src/HdrHistogram.UnitTests/ShortHistogramTests.cs
@@ -9,12 +9,21 @@ public class ShortHistogramTests : HistogramTestBase
protected override HistogramBase Create(long highestTrackableValue, int numberOfSignificantValueDigits)
{
- return new ShortHistogram(highestTrackableValue, numberOfSignificantValueDigits);
+ //return new ShortHistogram(highestTrackableValue, numberOfSignificantValueDigits);
+ return HistogramFactory.With16BitBucketSize()
+ .WithValuesUpTo(highestTrackableValue)
+ .WithPrecisionOf(numberOfSignificantValueDigits)
+ .Create();
}
protected override HistogramBase Create(long lowestTrackableValue, long highestTrackableValue, int numberOfSignificantValueDigits)
{
- return new ShortHistogram(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits);
+ //return new ShortHistogram(lowestTrackableValue, highestTrackableValue, numberOfSignificantValueDigits);
+ return HistogramFactory.With16BitBucketSize()
+ .WithValuesFrom(lowestTrackableValue)
+ .WithValuesUpTo(highestTrackableValue)
+ .WithPrecisionOf(numberOfSignificantValueDigits)
+ .Create();
}
}
}
\ No newline at end of file
diff --git a/src/HdrHistogram/HdrHistogram.csproj b/src/HdrHistogram/HdrHistogram.csproj
index ce9b333..f795f42 100644
--- a/src/HdrHistogram/HdrHistogram.csproj
+++ b/src/HdrHistogram/HdrHistogram.csproj
@@ -46,6 +46,8 @@
+
+
diff --git a/src/HdrHistogram/Histogram.cs b/src/HdrHistogram/Histogram.cs
new file mode 100644
index 0000000..47cc538
--- /dev/null
+++ b/src/HdrHistogram/Histogram.cs
@@ -0,0 +1,332 @@
+using System;
+
+namespace HdrHistogram
+{
+ ///
+ /// Provides factory methods to define the features of your histogram.
+ ///
+ public abstract class HistogramFactory
+ {
+ ///
+ /// Private constructor to force usage via the Static starter methods.
+ ///
+ private HistogramFactory()
+ {
+ }
+
+ ///
+ /// The lowest value that can be tracked (distinguished from 0) by the histogram.
+ /// Must be a positive integer that is >= 1.
+ /// May be internally rounded down to nearest power of 2.
+ ///
+ protected long LowestTrackableValue { get; set; } = 1;
+
+ ///
+ /// The highest value to be tracked by the histogram. Must be a positive integer that is >= (2 * ).
+ ///
+ protected long HighestTrackableValue { get; set; } = TimeStamp.Minutes(10);
+
+ ///
+ /// The number of significant decimal digits to which the histogram will maintain value resolution and separation.
+ /// Must be a non-negative integer between 0 and 5.
+ ///
+ protected int NumberOfSignificantValueDigits { get; set; } = 3;
+
+
+
+ ///
+ /// Specifies that the Histogram to be created should be thread safe when written to from multiple threads.
+ ///
+ /// Returns a that is set to return a threadsafe writer.
+ public abstract HistogramFactory WithThreadSafeWrites();
+
+ ///
+ /// Specifies that the consumer will need to be able to read Histogram values in a thread safe manner.
+ /// This will mean will be used to wrap the Histogram, allowing thread safe reads.
+ ///
+ /// Returns a which can create recorders. Recorders allow for threadsafe reads.
+ public abstract RecorderFactory WithThreadSafeReads();
+
+ ///
+ /// A factory-method to create the Histogram.
+ ///
+ ///
+ /// The lowest value that can be tracked (distinguished from 0) by the histogram.
+ /// Must be a positive integer that is >= 1.
+ /// May be internally rounded down to nearest power of 2.
+ ///
+ /// The highest value to be tracked by the histogram. Must be a positive integer that is >= (2 * ).
+ /// The number of significant decimal digits to which the histogram will maintain value resolution and separation.
+ /// Must be a non-negative integer between 0 and 5.
+ ///
+ /// Returns a newly created instance defined by the settings of the current instance of .
+ public abstract HistogramBase Create(
+ long lowestDiscernibleValue,
+ long highestTrackableValue,
+ int numberOfSignificantValueDigits);
+
+ ///
+ /// A factory-method to create the Histogram.
+ ///
+ /// An identifier for this instance.
+ ///
+ /// The lowest value that can be tracked (distinguished from 0) by the histogram.
+ /// Must be a positive integer that is >= 1.
+ /// May be internally rounded down to nearest power of 2.
+ ///
+ /// The highest value to be tracked by the histogram. Must be a positive integer that is >= (2 * ).
+ /// The number of significant decimal digits to which the histogram will maintain value resolution and separation.
+ /// Must be a non-negative integer between 0 and 5.
+ ///
+ /// Returns a newly created instance defined by the settings of the current instance of .
+ public abstract HistogramBase Create(
+ long instanceId,
+ long lowestDiscernibleValue,
+ long highestTrackableValue,
+ int numberOfSignificantValueDigits);
+
+ ///
+ /// Specifies the lowest value the Histogram should be configured to record.
+ ///
+ ///
+ /// The lowest value that can be tracked (distinguished from 0) by the histogram.
+ /// Must be a positive integer that is >= 1.
+ /// May be internally rounded down to nearest power of 2.
+ ///
+ /// The configured with the specified minimum allowed value.
+ public HistogramFactory WithValuesFrom(long lowestDiscernibleValue)
+ {
+ LowestTrackableValue = lowestDiscernibleValue;
+ return this;
+ }
+
+ ///
+ /// Specifies the highest value the Histogram should be configured to record.
+ ///
+ ///
+ /// The highest value to be tracked by the histogram. Must be a positive integer that is >= (2 * ).
+ ///
+ /// The configured with the specified maximum allowed value.
+ public HistogramFactory WithValuesUpTo(long highestTrackableValue)
+ {
+ HighestTrackableValue = highestTrackableValue;
+ return this;
+ }
+
+ ///
+ /// Specifies the number of significant figures that the Histogram should record.
+ ///
+ ///
+ /// The number of significant decimal digits to which the histogram will maintain value resolution and separation.
+ /// Must be a non-negative integer between 0 and 5.
+ ///
+ /// The configured with the specified maximum allowed value.
+ public HistogramFactory WithPrecisionOf(int numberOfSignificantValueDigits)
+ {
+ NumberOfSignificantValueDigits = numberOfSignificantValueDigits;
+ return this;
+ }
+
+ ///
+ /// Creates the histogram as configured by this factory instance.
+ ///
+ /// A newly created instance of .
+ public HistogramBase Create()
+ {
+ return Create(LowestTrackableValue, HighestTrackableValue, NumberOfSignificantValueDigits);
+ }
+
+
+
+
+ ///
+ /// Specify that the Histogram should be able to record count values in the 64bit range.
+ ///
+ /// The configured for 64bit bucket sizes.
+ public static HistogramFactory With64BitBucketSize()
+ {
+ return new LongHistogramFactory();
+ }
+
+ ///
+ /// Specify that the Histogram should be able to record count values in the 32bit range.
+ ///
+ /// The configured for 64bit bucket sizes.
+ public static HistogramFactory With32BitBucketSize()
+ {
+ return new IntHistogramFactory();
+ }
+
+ ///
+ /// Specify that the Histogram should be able to record count values in the 32bit range.
+ ///
+ /// The configured for 64bit bucket sizes.
+ public static HistogramFactory With16BitBucketSize()
+ {
+ return new ShortHistogramFactory();
+ }
+
+
+
+ private sealed class LongHistogramFactory : HistogramFactory
+ {
+ public override HistogramBase Create(long lowestDiscernibleValue, long highestTrackableValue, int numberOfSignificantValueDigits)
+ {
+ return new LongHistogram(lowestDiscernibleValue, highestTrackableValue, numberOfSignificantValueDigits);
+ }
+
+ public override HistogramBase Create(long instanceId, long lowestDiscernibleValue, long highestTrackableValue,
+ int numberOfSignificantValueDigits)
+ {
+ return new LongHistogram(instanceId, lowestDiscernibleValue, highestTrackableValue, numberOfSignificantValueDigits);
+ }
+
+ public override HistogramFactory WithThreadSafeWrites()
+ {
+ return new LongConcurrentHistogramFactory(this);
+ }
+
+ public override RecorderFactory WithThreadSafeReads()
+ {
+ return new RecorderFactory(this);
+ }
+ }
+
+ private sealed class IntHistogramFactory : HistogramFactory
+ {
+ public override HistogramBase Create(long lowestDiscernibleValue, long highestTrackableValue, int numberOfSignificantValueDigits)
+ {
+ return new IntHistogram(lowestDiscernibleValue, highestTrackableValue, numberOfSignificantValueDigits);
+ }
+
+ public override HistogramBase Create(long instanceId, long lowestDiscernibleValue, long highestTrackableValue,
+ int numberOfSignificantValueDigits)
+ {
+ return new IntHistogram(instanceId, lowestDiscernibleValue, highestTrackableValue, numberOfSignificantValueDigits);
+ }
+
+ public override HistogramFactory WithThreadSafeWrites()
+ {
+ return new IntConcurrentHistogramFactory(this);
+ }
+
+ public override RecorderFactory WithThreadSafeReads()
+ {
+ return new RecorderFactory(this);
+ }
+ }
+
+ private sealed class ShortHistogramFactory : HistogramFactory
+ {
+ public override HistogramBase Create(long lowestDiscernibleValue, long highestTrackableValue, int numberOfSignificantValueDigits)
+ {
+ return new ShortHistogram(lowestDiscernibleValue, highestTrackableValue, numberOfSignificantValueDigits);
+ }
+
+ public override HistogramBase Create(long instanceId, long lowestDiscernibleValue, long highestTrackableValue,
+ int numberOfSignificantValueDigits)
+ {
+ return new ShortHistogram(instanceId, lowestDiscernibleValue, highestTrackableValue, numberOfSignificantValueDigits);
+ }
+
+ public override HistogramFactory WithThreadSafeWrites()
+ {
+ throw new NotSupportedException("Short(16bit) Histograms do not support thread safe writes.");
+ }
+
+ public override RecorderFactory WithThreadSafeReads()
+ {
+ return new RecorderFactory(this);
+ }
+ }
+
+ private sealed class LongConcurrentHistogramFactory : HistogramFactory
+ {
+ public LongConcurrentHistogramFactory(HistogramFactory histogramFactory)
+ {
+ LowestTrackableValue = histogramFactory.LowestTrackableValue;
+ HighestTrackableValue = histogramFactory.HighestTrackableValue;
+ NumberOfSignificantValueDigits = histogramFactory.NumberOfSignificantValueDigits;
+ }
+
+ public override HistogramFactory WithThreadSafeWrites()
+ {
+ return this;
+ }
+
+ public override RecorderFactory WithThreadSafeReads()
+ {
+ return new RecorderFactory(this);
+ }
+
+ public override HistogramBase Create(long lowestDiscernibleValue, long highestTrackableValue, int numberOfSignificantValueDigits)
+ {
+ return new LongConcurrentHistogram(lowestDiscernibleValue, highestTrackableValue, numberOfSignificantValueDigits);
+ }
+
+ public override HistogramBase Create(long instanceId, long lowestDiscernibleValue, long highestTrackableValue,
+ int numberOfSignificantValueDigits)
+ {
+ return new LongConcurrentHistogram(instanceId, lowestDiscernibleValue, highestTrackableValue, numberOfSignificantValueDigits);
+ }
+ }
+
+ private sealed class IntConcurrentHistogramFactory : HistogramFactory
+ {
+ public IntConcurrentHistogramFactory(HistogramFactory histogramFactory)
+ {
+ LowestTrackableValue = histogramFactory.LowestTrackableValue;
+ HighestTrackableValue = histogramFactory.HighestTrackableValue;
+ NumberOfSignificantValueDigits = histogramFactory.NumberOfSignificantValueDigits;
+ }
+
+ public override HistogramFactory WithThreadSafeWrites()
+ {
+ return this;
+ }
+
+ public override RecorderFactory WithThreadSafeReads()
+ {
+ return new RecorderFactory(this);
+ }
+
+ public override HistogramBase Create(long lowestDiscernibleValue, long highestTrackableValue, int numberOfSignificantValueDigits)
+ {
+ return new IntConcurrentHistogram(lowestDiscernibleValue, highestTrackableValue, numberOfSignificantValueDigits);
+ }
+
+ public override HistogramBase Create(long instanceId, long lowestDiscernibleValue, long highestTrackableValue,
+ int numberOfSignificantValueDigits)
+ {
+ return new IntConcurrentHistogram(instanceId, lowestDiscernibleValue, highestTrackableValue, numberOfSignificantValueDigits);
+ }
+ }
+
+
+ ///
+ /// Factory for creating Recorders for thread safe reading of histograms.
+ ///
+ public sealed class RecorderFactory
+ {
+ private readonly HistogramFactory _histogramBuilder;
+
+ internal RecorderFactory(HistogramFactory histogramBuilder)
+ {
+ _histogramBuilder = histogramBuilder;
+ }
+
+ ///
+ /// Creates the recorder as configured by this factory instance.
+ ///
+ /// A newly created instance of .
+ public Recorder Create()
+ {
+ return new Recorder(
+ _histogramBuilder.LowestTrackableValue,
+ _histogramBuilder.HighestTrackableValue,
+ _histogramBuilder.NumberOfSignificantValueDigits,
+ _histogramBuilder.Create);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/HdrHistogram/HistogramFactoryDelegate.cs b/src/HdrHistogram/HistogramFactoryDelegate.cs
new file mode 100644
index 0000000..a026d16
--- /dev/null
+++ b/src/HdrHistogram/HistogramFactoryDelegate.cs
@@ -0,0 +1,20 @@
+namespace HdrHistogram
+{
+ ///
+ /// The method definition for a histogram factory.
+ ///
+ /// The instance id the histogram should be created with.
+ /// The lowest value that can be tracked (distinguished from 0) by the histogram.
+ /// Must be a positive integer that is >= 1.
+ /// May be internally rounded down to nearest power of 2.
+ ///
+ /// The highest value to be tracked by the histogram.
+ /// Must be a positive integer that is >= (2 * lowestTrackableValue).
+ ///
+ ///
+ /// The number of significant decimal digits to which the histogram will maintain value resolution and separation.
+ /// Must be a non-negative integer between 0 and 5.
+ ///
+ public delegate HistogramBase HistogramFactoryDelegate(
+ long instanceId, long lowestDiscernibleValue, long highestTrackableValue, int numberOfSignificantValueDigits);
+}
\ No newline at end of file
diff --git a/src/HdrHistogram/HistogramLogWriter.cs b/src/HdrHistogram/HistogramLogWriter.cs
index 59726d2..815f00a 100644
--- a/src/HdrHistogram/HistogramLogWriter.cs
+++ b/src/HdrHistogram/HistogramLogWriter.cs
@@ -1,5 +1,6 @@
using System;
using System.IO;
+using System.Threading;
using HdrHistogram.Utilities;
namespace HdrHistogram
@@ -14,6 +15,7 @@ public sealed class HistogramLogWriter : IDisposable
private readonly TextWriter _log;
private bool _hasHeaderWritten = false;
+ private int _isDisposed = 0;
///
/// Writes the provided histograms to the underlying with a given overall start time.
@@ -127,7 +129,10 @@ private void WriteHistogram(HistogramBase histogram)
///
public void Dispose()
{
- using (_log) { }
+ if (Interlocked.CompareExchange(ref _isDisposed, 1, 0) == 0)
+ {
+ using (_log) { }
+ }
}
}
}
\ No newline at end of file
diff --git a/src/HdrHistogram/Recorder.cs b/src/HdrHistogram/Recorder.cs
index eb12224..14ce366 100644
--- a/src/HdrHistogram/Recorder.cs
+++ b/src/HdrHistogram/Recorder.cs
@@ -12,24 +12,6 @@
namespace HdrHistogram
{
- ///
- /// The method definition for a histogram factory.
- ///
- /// The instance id the histogram should be created with.
- /// The lowest value that can be tracked (distinguished from 0) by the histogram.
- /// Must be a positive integer that is >= 1.
- /// May be internally rounded down to nearest power of 2.
- ///
- /// The highest value to be tracked by the histogram.
- /// Must be a positive integer that is >= (2 * lowestTrackableValue).
- ///
- ///
- /// The number of significant decimal digits to which the histogram will maintain value resolution and separation.
- /// Must be a non-negative integer between 0 and 5.
- ///
- public delegate HistogramBase HistogramFactory(
- long instanceId, long lowestDiscernibleValue, long highestTrackableValue, int numberOfSignificantValueDigits);
-
///
/// Records integer values, and provides stable interval samples from live recorded data without interrupting or stalling active recording of values.
/// Each interval histogram provided contains all value counts accumulated since the previous interval histogram was taken.
@@ -45,7 +27,7 @@ public class Recorder : IRecorder
private readonly object _gate = new object();
private readonly long _instanceId = Interlocked.Increment(ref _instanceIdSequencer);
private readonly WriterReaderPhaser _recordingPhaser = new WriterReaderPhaser();
- private readonly HistogramFactory _histogramFactory;
+ private readonly HistogramFactoryDelegate _histogramFactory;
private HistogramBase _activeHistogram;
private HistogramBase _inactiveHistogram;
@@ -69,7 +51,7 @@ public Recorder(
long lowestDiscernibleValue,
long highestTrackableValue,
int numberOfSignificantValueDigits,
- HistogramFactory histogramFactory)
+ HistogramFactoryDelegate histogramFactory)
{
_histogramFactory = histogramFactory;
_activeHistogram = histogramFactory(_instanceId, lowestDiscernibleValue, highestTrackableValue, numberOfSignificantValueDigits);
@@ -253,6 +235,5 @@ private void ValidateFitAsReplacementHistogram(HistogramBase replacementHistogra
$"Replacement histogram must have been obtained via a previous getIntervalHistogram() call from this {GetType().Name} instance");
}
}
-
}
}
\ No newline at end of file