Skip to content

Commit bbaf0fa

Browse files
authored
Merge pull request #30 from LeeCampbell/ConcurrentHistograms
Concurrent Long and Int histograms
2 parents c81852a + 340320b commit bbaf0fa

25 files changed

Lines changed: 1025 additions & 131 deletions

src/HdrHistogram.Benchmarking/Recording/Recording32BitBenchmark.cs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@ public class Recording32BitBenchmark
88
{
99
private readonly long[] _testValues;
1010
private readonly LongHistogram _longHistogram;
11+
private readonly LongConcurrentHistogram _longConcurrentHistogram;
1112
private readonly IntHistogram _intHistogram;
13+
private readonly IntConcurrentHistogram _intConcurrentHistogram;
1214
private readonly ShortHistogram _shortHistogram;
1315
private readonly Recorder _longRecorder;
16+
private readonly Recorder _longConcurrentRecorder;
1417
private readonly Recorder _intRecorder;
18+
private readonly Recorder _intConcurrentRecorder;
1519
private readonly Recorder _shortRecorder;
1620

1721
public Recording32BitBenchmark()
@@ -27,16 +31,21 @@ public Recording32BitBenchmark()
2731
x.Value+1,
2832
})
2933
.Where(x => x > 0)
30-
.Where(x=>x< highestTrackableValue)
34+
.Where(x => x < highestTrackableValue)
3135
.Distinct()
3236
.ToArray();
3337

3438
_longHistogram = new LongHistogram(highestTrackableValue, 3);
3539
_intHistogram = new IntHistogram(highestTrackableValue, 3);
3640
_shortHistogram = new ShortHistogram(highestTrackableValue, 3);
3741

42+
_longConcurrentHistogram = new LongConcurrentHistogram(1, highestTrackableValue, 3);
43+
_intConcurrentHistogram = new IntConcurrentHistogram(1, highestTrackableValue, 3);
44+
3845
_longRecorder = new Recorder(1, highestTrackableValue, 3, (id, low, hi, sf) => new LongHistogram(id, low, hi, sf));
46+
_longConcurrentRecorder = new Recorder(1, highestTrackableValue, 3, (id, low, hi, sf) => new LongConcurrentHistogram(id, low, hi, sf));
3947
_intRecorder = new Recorder(1, highestTrackableValue, 3, (id, low, hi, sf) => new IntHistogram(id, low, hi, sf));
48+
_intConcurrentRecorder = new Recorder(1, highestTrackableValue, 3, (id, low, hi, sf) => new IntConcurrentHistogram(id, low, hi, sf));
4049
_shortRecorder = new Recorder(1, highestTrackableValue, 3, (id, low, hi, sf) => new ShortHistogram(id, low, hi, sf));
4150
}
4251

@@ -53,6 +62,19 @@ public long LongHistogramRecording()
5362
return counter;
5463
}
5564

65+
[Benchmark]
66+
public long LongConcurrentHistogramRecording()
67+
{
68+
long counter = 0L;
69+
for (int i = 0; i < _testValues.Length; i++)
70+
{
71+
var value = _testValues[i];
72+
_longConcurrentHistogram.RecordValue(value);
73+
counter += value;
74+
}
75+
return counter;
76+
}
77+
5678
[Benchmark]
5779
public long IntHistogramRecording()
5880
{
@@ -66,6 +88,19 @@ public long IntHistogramRecording()
6688
return counter;
6789
}
6890

91+
[Benchmark]
92+
public long IntConcurrentHistogramRecording()
93+
{
94+
long counter = 0L;
95+
for (int i = 0; i < _testValues.Length; i++)
96+
{
97+
var value = _testValues[i];
98+
_intConcurrentHistogram.RecordValue(value);
99+
counter += value;
100+
}
101+
return counter;
102+
}
103+
69104
[Benchmark]
70105
public long ShortHistogramRecording()
71106
{
@@ -90,6 +125,20 @@ public long LongRecorderRecording()
90125
return counter;
91126
}
92127

128+
[Benchmark]
129+
public long LongConcurrentRecorderRecording()
130+
{
131+
long counter = 0L;
132+
133+
for (int i = 0; i < _testValues.Length; i++)
134+
{
135+
var value = _testValues[i];
136+
_longConcurrentRecorder.RecordValue(value);
137+
counter += value;
138+
}
139+
return counter;
140+
}
141+
93142
[Benchmark]
94143
public long IntRecorderRecording()
95144
{
@@ -103,6 +152,19 @@ public long IntRecorderRecording()
103152
return counter;
104153
}
105154

155+
[Benchmark]
156+
public long IntConcurrentRecorderRecording()
157+
{
158+
long counter = 0L;
159+
for (int i = 0; i < _testValues.Length; i++)
160+
{
161+
var value = _testValues[i];
162+
_intConcurrentRecorder.RecordValue(value);
163+
counter += value;
164+
}
165+
return counter;
166+
}
167+
106168
[Benchmark]
107169
public long ShortRecorderRecording()
108170
{
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
using System.Linq;
3+
using System.Threading.Tasks;
4+
using NUnit.Framework;
5+
6+
namespace HdrHistogram.UnitTests
7+
{
8+
public abstract class ConcurrentHistogramTestBase : HistogramTestBase
9+
{
10+
[Test]
11+
public void Can_support_multiple_concurrent_recorders()
12+
{
13+
var target = Create(DefautltLowestDiscernibleValue, DefaultHighestTrackableValue, DefaultSignificantFigures);
14+
const int loopcount = 10 * 1000 * 1000;
15+
var concurrency = Environment.ProcessorCount;
16+
var expected = loopcount * concurrency;
17+
Action foo = () =>
18+
{
19+
for (var i = 0; i < loopcount; i++)
20+
target.RecordValue(i);
21+
};
22+
23+
var actions = Enumerable.Range(1, concurrency)
24+
.Select(_ => foo)
25+
.ToArray();
26+
Parallel.Invoke(actions);
27+
28+
Assert.AreEqual(expected, target.TotalCount);
29+
}
30+
}
31+
}

src/HdrHistogram.UnitTests/HdrHistogram.UnitTests.csproj

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,18 @@
4949
<Reference Include="System.Xml" />
5050
</ItemGroup>
5151
<ItemGroup>
52+
<Compile Include="ConcurrentHistogramTestBase.cs" />
53+
<Compile Include="HistogramEncodingTestBase.cs" />
54+
<Compile Include="IntConcurrentHistogramTests.cs" />
55+
<Compile Include="IntHistogramEncodingTests.cs" />
56+
<Compile Include="LongConcurrentHistogramTests.cs" />
5257
<Compile Include="HistogramAssert.cs" />
53-
<Compile Include="HistogramEncodingTest.cs" />
58+
<Compile Include="LongHistogramEncodingTests.cs" />
5459
<Compile Include="HistogramIterationValueComparer.cs" />
60+
<Compile Include="Persistence\LongConcurrentHistogramLogReaderWriterTests.cs" />
5561
<Compile Include="Persistence\HistogramLogExtensions.cs" />
5662
<Compile Include="Persistence\HistogramLogReaderWriterTestBase.cs" />
63+
<Compile Include="Persistence\IntConcurrentHistogramLogReaderWriterTests.cs" />
5764
<Compile Include="Persistence\IntHistogramLogReaderWriterTests.cs" />
5865
<Compile Include="HistogramTestBase.cs" />
5966
<Compile Include="IntHistogramTests.cs" />
@@ -65,9 +72,12 @@
6572
<Compile Include="Persistence\TestCaseGenerator.cs" />
6673
<Compile Include="Properties\AssemblyInfo.cs" />
6774
<Compile Include="Recording\RecorderTestsBase.cs" />
75+
<Compile Include="Recording\RecorderTestWithIntConcurrentHistogram.cs" />
6876
<Compile Include="Recording\RecorderTestWithIntHistogram.cs" />
77+
<Compile Include="Recording\RecorderTestWithLongConcurrentHistogram.cs" />
6978
<Compile Include="Recording\RecorderTestWithLongHistogram.cs" />
7079
<Compile Include="Recording\RecorderTestWithLShortHistogram.cs" />
80+
<Compile Include="ShortHistogramEncodingTests.cs" />
7181
<Compile Include="ShortHistogramTests.cs" />
7282
<Compile Include="TimeStampTests.cs" />
7383
</ItemGroup>

src/HdrHistogram.UnitTests/HgrmPercentileDistrubutionOutputTests.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ public void PercentileDistrubution_hgrm_output_is_in_correct_format(
2727
histogram.OutputPercentileDistribution(writer, percentileTicksPerHalfDistance, scaling);
2828
var actual = writer.ToString();
2929

30-
3130
Assert.AreEqual(expected, actual);
3231
}
3332

@@ -68,7 +67,7 @@ private string GetEmbeddedFileText(string filename)
6867
}
6968
}
7069

71-
private static void LoadHistogram(HistogramBase histogram)
70+
private static void LoadHistogram(IRecorder histogram)
7271
{
7372
for (int i = 0; i < 10000; i += 1000)
7473
{
Lines changed: 24 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,86 @@
1-
/*
2-
* Written by Matt Warren, and released to the public domain,
3-
* as explained at
4-
* http://creativecommons.org/publicdomain/zero/1.0/
5-
*
6-
* This is a .NET port of the original Java version, which was written by
7-
* Gil Tene as described in
8-
* https://github.com/HdrHistogram/HdrHistogram
9-
*/
10-
11-
using HdrHistogram.Encoding;
1+
using HdrHistogram.Encoding;
122
using HdrHistogram.Utilities;
133
using NUnit.Framework;
144

155
namespace HdrHistogram.UnitTests
166
{
17-
[TestFixture]
18-
public sealed class LongHistogramEncodingTests
7+
public abstract class HistogramEncodingTestBase
198
{
20-
private static readonly HistogramEncoderV2 EncoderV2 = new Encoding.HistogramEncoderV2();
21-
private const long HighestTrackableValue = 3600L * 1000 * 1000; // e.g. for 1 hr in usec units
9+
protected const long DefautltLowestDiscernibleValue = 1;
10+
protected const long DefaultHighestTrackableValue = 7716549600;//TimeStamp.Hours(1); // e.g. for 1 hr in system clock ticks (StopWatch.Frequency)
11+
protected const int DefaultSignificantFigures = 3;
2212

23-
13+
private static readonly HistogramEncoderV2 EncoderV2 = new Encoding.HistogramEncoderV2();
2414

2515
[Test]
2616
public void Given_a_populated_Histogram_When_encoded_and_decoded_Then_data_is_preserved()
2717
{
28-
var source = Create(HighestTrackableValue, 3);
18+
var source = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
2919
Load(source);
3020
var result = EncodeDecode(source);
31-
HistogramAssert.AreEqual(source, result);
21+
HistogramAssert.AreValueEqual(source, result);
3222
}
3323

3424
[Test]
3525
public void Given_a_populated_Histogram_When_encoded_and_decoded_with_compression_Then_data_is_preserved()
3626
{
37-
var source = Create(HighestTrackableValue, 3);
27+
var source = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
3828
Load(source);
3929
var result = CompressedEncodeDecode(source);
40-
HistogramAssert.AreEqual(source, result);
30+
HistogramAssert.AreValueEqual(source, result);
4131
}
4232

4333
[Test]
4434
public void Given_a_Histogram_populated_with_full_range_of_values_When_encoded_and_decoded_Then_data_is_preserved()
4535
{
46-
var source = Create(HighestTrackableValue, 3);
36+
var source = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
4737
LoadFullRange(source);
4838
var result = EncodeDecode(source);
49-
HistogramAssert.AreEqual(source, result);
39+
HistogramAssert.AreValueEqual(source, result);
5040
}
5141

5242
[Test]
5343
public void Given_a_Histogram_populated_with_full_range_of_values_When_encoded_and_decoded_with_compression_Then_data_is_preserved()
5444
{
55-
var source = Create(HighestTrackableValue, 3);
45+
var source = Create(DefaultHighestTrackableValue, DefaultSignificantFigures);
5646
LoadFullRange(source);
5747
var result = CompressedEncodeDecode(source);
58-
HistogramAssert.AreEqual(source, result);
48+
HistogramAssert.AreValueEqual(source, result);
5949
}
6050

61-
private LongHistogram Create(long highestTrackableValue, int numberOfSignificantDigits)
62-
{
63-
return new LongHistogram(highestTrackableValue, numberOfSignificantDigits);
64-
}
51+
protected abstract HistogramBase Create(long highestTrackableValue, int numberOfSignificantDigits);
6552

66-
private static LongHistogram EncodeDecode(LongHistogram source)
53+
private static HistogramBase EncodeDecode(HistogramBase source)
6754
{
6855
var targetBuffer = ByteBuffer.Allocate(source.GetNeededByteBufferCapacity());
6956
source.Encode(targetBuffer, EncoderV2);
7057
targetBuffer.Position = 0;
71-
return (LongHistogram)HistogramEncoding.DecodeFromByteBuffer(targetBuffer, 0);
58+
return HistogramEncoding.DecodeFromByteBuffer(targetBuffer, 0);
7259
}
7360

74-
private static LongHistogram CompressedEncodeDecode(LongHistogram source)
61+
private static HistogramBase CompressedEncodeDecode(HistogramBase source)
7562
{
7663
var targetBuffer = ByteBuffer.Allocate(source.GetNeededByteBufferCapacity());
7764
source.EncodeIntoCompressedByteBuffer(targetBuffer);
7865
targetBuffer.Position = 0;
79-
return (LongHistogram)HistogramEncoding.DecodeFromCompressedByteBuffer(targetBuffer, 0);
66+
return HistogramEncoding.DecodeFromCompressedByteBuffer(targetBuffer, 0);
8067
}
8168

82-
private static void Load(LongHistogram source)
69+
private static void Load(IRecorder source)
8370
{
8471
for (long i = 0L; i < 10000L; i++)
8572
{
8673
source.RecordValue(1000L * i);
8774
}
8875
}
8976

90-
private static void LoadFullRange(LongHistogram source)
77+
protected virtual void LoadFullRange(IRecorder source)
9178
{
92-
for (long i = 0L; i < HighestTrackableValue; i += 100L)
79+
for (long i = 0L; i < DefaultHighestTrackableValue; i += 100L)
9380
{
9481
source.RecordValue(i);
9582
}
96-
source.RecordValue(HighestTrackableValue);
83+
source.RecordValue(DefaultHighestTrackableValue);
9784
}
98-
9985
}
100-
}
86+
}

0 commit comments

Comments
 (0)