Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 66 additions & 58 deletions README.md

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions src/HdrHistogram.Examples/SimpleHistogramExample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace HdrHistogram.Examples
/// </summary>
static class SimpleHistogramExample
{
private static readonly LongHistogram Histogram = new LongHistogram(TimeSpan.TicksPerHour, 3);
private static readonly LongHistogram Histogram = new LongHistogram(TimeStamp.Hours(1), 3);
private static volatile Socket _socket;
private static readonly Lazy<AddressFamily> AddressFamily = new Lazy<AddressFamily>(() => GetAddressFamily("google.com"));

Expand Down Expand Up @@ -57,20 +57,20 @@ private static void OutputMeasurements()
var size = Histogram.GetEstimatedFootprintInBytes();
Console.WriteLine("Histogram size = {0} bytes ({1:F2} MB)", size, size / 1024.0 / 1024.0);

Console.WriteLine("Recorded latencies [in ticks] for Create+Close of a DatagramSocket:");
Console.WriteLine("Recorded latencies [in system clock ticks] for Create+Close of a DatagramSocket:");
Histogram.OutputPercentileDistribution(Console.Out, outputValueUnitScalingRatio: OutputScalingFactor.None);
Console.WriteLine();

Console.WriteLine("Recorded latencies [in usec] for Create+Close of a DatagramSocket:");
Histogram.OutputPercentileDistribution(Console.Out, outputValueUnitScalingRatio: OutputScalingFactor.TicksToMicroseconds);
Histogram.OutputPercentileDistribution(Console.Out, outputValueUnitScalingRatio: OutputScalingFactor.TimeStampToMicroseconds);
Console.WriteLine();

Console.WriteLine("Recorded latencies [in msec] for Create+Close of a DatagramSocket:");
Histogram.OutputPercentileDistribution(Console.Out, outputValueUnitScalingRatio: OutputScalingFactor.TicksToMilliseconds);
Histogram.OutputPercentileDistribution(Console.Out, outputValueUnitScalingRatio: OutputScalingFactor.TimeStampToMilliseconds);
Console.WriteLine();

Console.WriteLine("Recorded latencies [in sec] for Create+Close of a DatagramSocket:");
Histogram.OutputPercentileDistribution(Console.Out, outputValueUnitScalingRatio: OutputScalingFactor.TicksToSeconds);
Histogram.OutputPercentileDistribution(Console.Out, outputValueUnitScalingRatio: OutputScalingFactor.TimeStampToSeconds);
}

private static void CreateAndCloseDatagramSocket()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
using System;
using System.Globalization;
using System.Globalization;
using System.IO;
using NUnit.Framework;

namespace HdrHistogram.UnitTests
{
/// <summary>
/// Validates against files generated by the official Java implementation.
/// </summary>
[TestFixture]
public sealed class HgrmPercentileDistrubutionOutputTests
{
[Test, Combinatorial]
public void PercentileDistrubution_hgrm_output_is_in_correct_format(
[Values(TimeSpan.TicksPerHour)]long highestTrackableValue,
[Values(36000000000)]long highestTrackableValue,
[Values(1, 2, 3, 4, 5)]int signigicantDigits,
[Values(10000.0)]double scaling,
[Values(5, 10, 20)]int percentileTicksPerHalfDistance)
Expand All @@ -31,7 +33,7 @@ public void PercentileDistrubution_hgrm_output_is_in_correct_format(

[Test, Combinatorial]
public void PercentileDistrubution_csv_output_is_in_correct_format(
[Values(TimeSpan.TicksPerHour)]long highestTrackableValue,
[Values(36000000000)]long highestTrackableValue,
[Values(1, 2, 3, 4, 5)]int signigicantDigits,
[Values(10000.0)]double scaling,
[Values(5, 10, 20)]int percentileTicksPerHalfDistance)
Expand Down
2 changes: 1 addition & 1 deletion src/HdrHistogram.UnitTests/HistogramTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace HdrHistogram.UnitTests
{
public abstract class HistogramTestBase
{
private const long HighestTrackableValue = TimeSpan.TicksPerHour; // e.g. for 1 hr in ticks
private const long HighestTrackableValue = 7716549600;//TimeStamp.Hours(1); // e.g. for 1 hr in system clock ticks (StopWatch.Frequency)
private const int NumberOfSignificantValueDigits = 3;
private const long TestValueLevel = 4;

Expand Down
6 changes: 3 additions & 3 deletions src/HdrHistogram/HistogramBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace HdrHistogram
/// 36,000,000,000 while maintaining a value precision of 3 significant digits across that range.
/// Value quantization within the range will thus be no larger than 1/1,000th (or 0.1%) of any value.
/// This example Histogram could be used to track and analyze the counts of observed response times ranging between
/// 1 tick (100 nanoseconds) and 1 hour in magnitude, while maintaining a value resolution of 100 nanosecond up to
/// 100 nanoseconds and 1 hour in magnitude, while maintaining a value resolution of 100 nanosecond up to
/// 100 microseconds, a resolution of 1 millisecond(or better) up to one second, and a resolution of 1 second
/// (or better) up to 1,000 seconds.
/// At it's maximum tracked value(1 hour), it would still maintain a resolution of 3.6 seconds (or better).
Expand Down Expand Up @@ -122,8 +122,8 @@ public abstract class HistogramBase
/// <remarks>
/// Providing a lowestTrackableValue is useful in situations where the units used for the histogram's values are much
/// smaller that the minimal accuracy required.
/// For example when tracking time values stated in ticks (100 nanoseconds), where the minimal accuracy required is a
/// microsecond, the proper value for lowestTrackableValue would be 10.
/// For example when tracking time values stated in nanoseconds, where the minimal accuracy required is a
/// microsecond, the proper value for <paramref name="lowestTrackableValue"/> would be 1000.
/// </remarks>
protected HistogramBase(long lowestTrackableValue, long highestTrackableValue, int numberOfSignificantValueDigits)
{
Expand Down
20 changes: 12 additions & 8 deletions src/HdrHistogram/HistogramExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public static IEnumerable<HistogramIterationValue> Percentiles(this HistogramBas
public static void OutputPercentileDistribution(this HistogramBase histogram,
TextWriter writer,
int percentileTicksPerHalfDistance = 5,
double outputValueUnitScalingRatio = OutputScalingFactor.TicksToMilliseconds,
double outputValueUnitScalingRatio = OutputScalingFactor.None,
bool useCsvFormat = false)
{
var formatter = useCsvFormat
Expand Down Expand Up @@ -144,17 +144,22 @@ public static void OutputPercentileDistribution(this HistogramBase histogram,

/// <summary>
/// Executes the action and records the time to complete the action.
/// The time is recorded in ticks.
/// The time is recorded in system clock ticks.
/// This time may vary between frameworks and platforms, but is equivalent to <c>(1/Stopwatch.Frequency)</c> seconds.
/// Note this is a convenience method and can carry a cost.
/// If the <paramref name="action"/> delegate is not cached, then it may incur an allocation cost for each invocation of <see cref="Record"/>
/// </summary>
/// <param name="histogram">The Histogram to record the latency in.</param>
/// <param name="action">The functionality to execute and measure</param>
/// <remarks>
/// <para>
/// Ticks are used as the unit of recording here as they are the smallest unit that .NET can measure
/// and require no conversion at time of recording. Instead conversion (scaling) can be done at time
/// of output to microseconds, milliseconds, seconds or other appropriate unit.
/// The units returned from <code>Stopwatch.GetTimestamp()</code> are used as the unit of
/// recording here as they are the smallest unit that .NET can measure and require no
/// conversion at time of recording.
/// Instead conversion (scaling) can be done at time of output to microseconds, milliseconds,
/// seconds or other appropriate unit.
/// These units are sometimes refered to as ticks, but should not not to be confused with
/// ticks used in <seealso cref="DateTime"/> or <seealso cref="TimeSpan"/>.
/// </para>
/// <para>
/// If you are able to cache the <paramref name="action"/> delegate, then doing so is encouraged.
Expand Down Expand Up @@ -187,9 +192,8 @@ public static void Record(this HistogramBase histogram, Action action)
{
var start = Stopwatch.GetTimestamp();
action();
var elapsedTicks = (Stopwatch.GetTimestamp() - start);
histogram.RecordValue(elapsedTicks);
var elapsed = Stopwatch.GetTimestamp() - start;
histogram.RecordValue(elapsed);
}
}

}
4 changes: 2 additions & 2 deletions src/HdrHistogram/IntHistogram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace HdrHistogram
/// 36,000,000,000 while maintaining a value precision of 3 significant digits across that range.
/// Value quantization within the range will thus be no larger than 1/1,000th (or 0.1%) of any value.
/// This example Histogram could be used to track and analyze the counts of observed response times ranging between
/// 1 tick (100 nanoseconds) and 1 hour in magnitude, while maintaining a value resolution of 100 nanosecond up to
/// 100 nanoseconds and 1 hour in magnitude, while maintaining a value resolution of 100 nanosecond up to
/// 100 microseconds, a resolution of 1 millisecond(or better) up to one second, and a resolution of 1 second
/// (or better) up to 1,000 seconds.
/// At it's maximum tracked value(1 hour), it would still maintain a resolution of 3.6 seconds (or better).
Expand Down Expand Up @@ -52,7 +52,7 @@ public IntHistogram(long highestTrackableValue, int numberOfSignificantValueDigi
/// <summary>
/// Construct a <see cref="IntHistogram"/> given the lowest and highest values to be tracked and a number of significant decimal digits.
/// Providing a <paramref name="lowestTrackableValue"/> is useful is situations where the units used for the histogram's values are much smaller that the minimal accuracy required.
/// For example when tracking time values stated in ticks (100 nanosecond units), where the minimal accuracy required is a microsecond, the proper value for <paramref name="lowestTrackableValue"/> would be 10.
/// For example when tracking time values stated in nanoseconds, where the minimal accuracy required is a microsecond, the proper value for <paramref name="lowestTrackableValue"/> would be 1000.
/// </summary>
/// <param name="lowestTrackableValue">
/// The lowest value that can be tracked (distinguished from 0) by the histogram.
Expand Down
4 changes: 2 additions & 2 deletions src/HdrHistogram/LongHistogram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace HdrHistogram
/// 36,000,000,000 while maintaining a value precision of 3 significant digits across that range.
/// Value quantization within the range will thus be no larger than 1/1,000th (or 0.1%) of any value.
/// This example Histogram could be used to track and analyze the counts of observed response times ranging between
/// 1 tick (100 nanoseconds) and 1 hour in magnitude, while maintaining a value resolution of 100 nanosecond up to
/// 100 nanoseconds and 1 hour in magnitude, while maintaining a value resolution of 100 nanosecond up to
/// 100 microseconds, a resolution of 1 millisecond(or better) up to one second, and a resolution of 1 second
/// (or better) up to 1,000 seconds.
/// At it's maximum tracked value(1 hour), it would still maintain a resolution of 3.6 seconds (or better).
Expand Down Expand Up @@ -51,7 +51,7 @@ public LongHistogram(long highestTrackableValue, int numberOfSignificantValueDig
/// <summary>
/// Construct a <see cref="LongHistogram"/> given the lowest and highest values to be tracked and a number of significant decimal digits.
/// Providing a <paramref name="lowestTrackableValue"/> is useful is situations where the units used for the histogram's values are much smaller that the minimal accuracy required.
/// For example when tracking time values stated in tick (100 nanosecond units), where the minimal accuracy required is a microsecond, the proper value for <paramref name="lowestTrackableValue"/> would be 10.
/// For example when tracking time values stated in nanosecond units, where the minimal accuracy required is a microsecond, the proper value for <paramref name="lowestTrackableValue"/> would be 1000.
/// </summary>
/// <param name="lowestTrackableValue">
/// The lowest value that can be tracked (distinguished from 0) by the histogram.
Expand Down
35 changes: 26 additions & 9 deletions src/HdrHistogram/OutputScalingFactor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/

using System;
using System.Diagnostics;

namespace HdrHistogram
{
Expand All @@ -16,23 +16,40 @@ namespace HdrHistogram
public static class OutputScalingFactor
{
/// <summary>
/// For use when values are recorded in ticks and output should be in ticks
/// For use when values are recorded and reported in the same unit of measurement.
/// </summary>
public const double None = 1.0;

/// <summary>
/// For use when values are recorded in ticks and output should be measured in microseconds.
/// For use when values are recorded with <seealso cref="Stopwatch.GetTimestamp()"/> and output should be reported in microseconds.
/// </summary>
public const double TicksToMicroseconds = 10.0;
public static readonly double TimeStampToMicroseconds = Stopwatch.Frequency / (1000d * 1000d);

/// <summary>
/// For use when values are recorded in ticks and output should be measured in milliseconds.
/// For use when values are recorded with <seealso cref="Stopwatch.GetTimestamp()"/> and output should be reported in milliseconds.
/// </summary>
public const double TicksToMilliseconds = TimeSpan.TicksPerMillisecond;
public static readonly double TimeStampToMilliseconds = Stopwatch.Frequency / 1000d;

/// <summary>
/// For use when values are recorded in ticks and output should be measured in seconds.
/// For use when values are recorded with <seealso cref="Stopwatch.GetTimestamp()"/> and output should be reported in seconds.
/// </summary>
public const double TicksToSeconds = TimeSpan.TicksPerSecond;
public static readonly double TimeStampToSeconds = Stopwatch.Frequency;
}

public static class TimeStamp
{
public static long Seconds(int seconds)
{
return Stopwatch.Frequency*seconds;
}

public static long Minutes(int minutes)
{
return Stopwatch.Frequency * minutes * 60L;
}
public static long Hours(int hours)
{
return Stopwatch.Frequency * hours * 60L * 60L;
}
}
}
4 changes: 2 additions & 2 deletions src/HdrHistogram/ShortHistogram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace HdrHistogram
/// 36,000,000,000 while maintaining a value precision of 3 significant digits across that range.
/// Value quantization within the range will thus be no larger than 1/1,000th (or 0.1%) of any value.
/// This example Histogram could be used to track and analyze the counts of observed response times ranging between
/// 1 tick (100 nanoseconds) and 1 hour in magnitude, while maintaining a value resolution of 100 nanosecond up to
/// 100 nanoseconds and 1 hour in magnitude, while maintaining a value resolution of 100 nanosecond up to
/// 100 microseconds, a resolution of 1 millisecond(or better) up to one second, and a resolution of 1 second
/// (or better) up to 1,000 seconds.
/// At it's maximum tracked value(1 hour), it would still maintain a resolution of 3.6 seconds (or better).
Expand Down Expand Up @@ -53,7 +53,7 @@ public ShortHistogram(long highestTrackableValue, int numberOfSignificantValueDi
/// <summary>
/// Construct a <see cref="ShortHistogram"/> given the lowest and highest values to be tracked and a number of significant decimal digits.
/// Providing a <paramref name="lowestTrackableValue"/> is useful is situations where the units used for the histogram's values are much smaller that the minimal accuracy required.
/// For example when tracking time values stated in ticks (100 nanosecond units), where the minimal accuracy required is a microsecond, the proper value for <paramref name="lowestTrackableValue"/> would be 10.
/// For example when tracking time values stated in nanoseconds, where the minimal accuracy required is a microsecond, the proper value for <paramref name="lowestTrackableValue"/> would be 1000.
/// </summary>
/// <param name="lowestTrackableValue">
/// The lowest value that can be tracked (distinguished from 0) by the histogram.
Expand Down
3 changes: 2 additions & 1 deletion src/HdrHistogram/Utilities/Bitwise.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ static Bitwise()
}
public static int NumberOfLeadingZeros(long value)
{
//Optimisation for 32 bit values. So for any value under 00:03:34.7 when measuring in ticks, we will hit a fast path.
//Optimisation for 32 bit values. So values under 00:16:41.0 when measuring with Stopwatch.GetTimestamp()*, we will hit a fast path.
// * as at writing on Win10 .NET 4.6
if (value < int.MaxValue)
return 63 - Log2((int)value);
return NumberOfLeadingZerosLong(value);
Expand Down