Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Binary search for large bucket count histograms #3252

Merged
merged 51 commits into from
Sep 2, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
a69121c
Binary search for large bucket count histograms
mic-max May 4, 2022
6e446cd
Update CHANGELOG.md
mic-max May 4, 2022
e420a15
netcoreapp3.1 was complaining
mic-max May 4, 2022
e8913b2
ci rerun
mic-max May 4, 2022
4ade35a
ci rerun
mic-max May 4, 2022
52e2c43
Update MetricTestData.cs
mic-max May 4, 2022
f7e88af
use 400 buckets
mic-max May 12, 2022
51d7219
Update ExplicitBucketHistogramConfiguration.cs
mic-max May 4, 2022
1bb61e9
separate nan part
mic-max May 12, 2022
685b46e
Address PR comments
mic-max May 12, 2022
773fefd
Merge branch 'hist-binary' of https://github.com/mic-max/opentelemetr…
mic-max May 12, 2022
de60b0e
update to 140
mic-max May 12, 2022
020c42e
remove double.nan from invalid hist bounds
mic-max May 12, 2022
daf1a80
Refactor and perf to histogram bucket index find
mic-max May 25, 2022
5bc4998
fine tune bound limit to switch to binary search
mic-max May 26, 2022
e84127a
included benchmark results in comment
mic-max May 26, 2022
0e939b6
new bench result
mic-max May 26, 2022
fb1ad6b
histogram stress test update
mic-max Jun 9, 2022
99bd6f1
Merge remote-tracking branch 'upstream/main' into hist-binary
mic-max Jun 28, 2022
05cc3c1
fix changelog
mic-max Jun 28, 2022
15c3464
spacing fix
mic-max Jun 28, 2022
a2c0e5d
sealed bucket class
mic-max Jul 1, 2022
ef28da0
ci
mic-max Jul 1, 2022
1810ddd
Merge branch 'main' into hist-binary
mic-max Jul 1, 2022
543a6d5
double.negative infinity
mic-max Jul 5, 2022
19ddae3
Merge branch 'hist-binary' of https://github.com/mic-max/opentelemetr…
mic-max Jul 5, 2022
f2a20f7
update order of operations
mic-max Jul 5, 2022
c9f3a3d
remove stress test change
mic-max Jul 5, 2022
a201b86
ci
mic-max Jul 5, 2022
d0d92a7
Add histogram binary mode tests
mic-max Jul 6, 2022
7f8d32b
ci
mic-max Jul 6, 2022
53ad017
Merge branch 'main' into hist-binary
utpilla Jul 6, 2022
b41879c
Merge branch 'main' into hist-binary
mic-max Jul 8, 2022
dbc5f3e
pr review changes
mic-max Jul 11, 2022
3046ac7
Merge branch 'hist-binary' of https://github.com/mic-max/opentelemetr…
mic-max Jul 11, 2022
881caca
Merge branch 'main' into hist-binary
mic-max Jul 11, 2022
370fb1a
allocated column - hist benchmark
mic-max Jul 12, 2022
07689ac
Merge branch 'hist-binary' of https://github.com/mic-max/opentelemetr…
mic-max Jul 12, 2022
4fe19f9
Merge branch 'main' into hist-binary
mic-max Jul 12, 2022
4d97b4e
Merge branch 'main' into hist-binary
utpilla Jul 15, 2022
8307bf8
Merge branch 'main' into hist-binary
mic-max Jul 26, 2022
3b2f762
CI
mic-max Jul 26, 2022
2030736
Merge branch 'hist-binary' of https://github.com/mic-max/opentelemetr…
mic-max Jul 26, 2022
42b1def
Merge branch 'main' into hist-binary
utpilla Jul 27, 2022
adb6945
Merge branch 'main' into hist-binary
utpilla Jul 28, 2022
90a95e6
Merge branch 'hist-binary' of https://github.com/mic-max/opentelemetr…
mic-max Aug 2, 2022
21de441
Merge branch 'main' into hist-binary
mic-max Aug 3, 2022
7806dbc
Merge branch 'main' into hist-binary
mic-max Aug 9, 2022
e7212ac
Merge branch 'main' into hist-binary
mic-max Aug 25, 2022
9a3025c
Merge branch 'main' into hist-binary
mic-max Aug 31, 2022
2bb1212
Merge branch 'main' into hist-binary
cijothomas Sep 2, 2022
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
5 changes: 4 additions & 1 deletion src/OpenTelemetry/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

## Unreleased

* Use binary search for histograms with a large amount of buckets.
mic-max marked this conversation as resolved.
Show resolved Hide resolved
([#3252](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3252))

* Exposed public setters for `LogRecord.State`, `LogRecord.StateValues`,
and `LogRecord.FormattedMessage`.
([#3217](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3217))
([#3217](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3217))

## 1.3.0-beta.1

Expand Down
2 changes: 2 additions & 0 deletions src/OpenTelemetry/Metrics/Metric.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public sealed class Metric
{
internal static readonly double[] DefaultHistogramBounds = new double[] { 0, 5, 10, 25, 50, 75, 100, 250, 500, 1000 };

internal static readonly int DefaultHistogramCountForBinarySearch = 400;
mic-max marked this conversation as resolved.
Show resolved Hide resolved

private readonly AggregatorStore aggStore;

internal Metric(
Expand Down
58 changes: 49 additions & 9 deletions src/OpenTelemetry/Metrics/MetricPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public struct MetricPoint

private readonly AggregationType aggType;

private readonly Func<double[], double, int> findHistogramBucketIndex = FindHistogramBucketIndexLinear;

private HistogramBuckets histogramBuckets;

// Represents temporality adjusted "value" for double/long metric types or "count" when histogram
Expand Down Expand Up @@ -61,6 +63,10 @@ internal MetricPoint(
if (this.aggType == AggregationType.Histogram)
{
this.histogramBuckets = new HistogramBuckets(histogramExplicitBounds);
if (histogramExplicitBounds.Length >= Metric.DefaultHistogramCountForBinarySearch)
{
this.findHistogramBucketIndex = FindHistogramBucketIndexBinary;
}
}
else if (this.aggType == AggregationType.HistogramSumCount)
{
Expand Down Expand Up @@ -324,15 +330,7 @@ internal void Update(double number)

case AggregationType.Histogram:
{
int i;
for (i = 0; i < this.histogramBuckets.ExplicitBounds.Length; i++)
{
// Upper bound is inclusive
if (number <= this.histogramBuckets.ExplicitBounds[i])
{
break;
}
}
int i = this.findHistogramBucketIndex(this.histogramBuckets.ExplicitBounds, number);

var sw = default(SpinWait);
while (true)
Expand Down Expand Up @@ -545,5 +543,47 @@ private readonly void ThrowNotSupportedMetricTypeException(string methodName)
{
throw new NotSupportedException($"{methodName} is not supported for this metric type.");
}

#pragma warning disable SA1204 // Static elements should appear before instance elements
private static int FindHistogramBucketIndexLinear(double[] bounds, double number)
#pragma warning restore SA1204 // Static elements should appear before instance elements
{
int i;

for (i = 0; i < bounds.Length; i++)
{
if (number <= bounds[i])
{
break;
}
}

return i;
}

private static int FindHistogramBucketIndexBinary(double[] bounds, double number)
mic-max marked this conversation as resolved.
Show resolved Hide resolved
{
var left = 0;
var right = bounds.Length - 1;

while (left <= right)
{
var mid = (int)Math.Floor((double)(left + right) / 2);
mic-max marked this conversation as resolved.
Show resolved Hide resolved
if (number == bounds[mid])
{
return mid;
}
else if (number > bounds[mid])
{
left = mid + 1;
}
else
{
right = mid - 1;
}
}

return right + 1;
}
}
}
54 changes: 27 additions & 27 deletions test/Benchmarks/Metrics/HistogramBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,50 +24,50 @@
using OpenTelemetry.Tests;

/*
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.22000
Intel Core i7-9700 CPU 3.00GHz, 1 CPU, 8 logical and 8 physical cores
.NET SDK=6.0.200
[Host] : .NET 6.0.2 (6.0.222.6406), X64 RyuJIT
DefaultJob : .NET 6.0.2 (6.0.222.6406), X64 RyuJIT
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19044.1706 (21H2)
AMD Ryzen 9 3900X, 1 CPU, 24 logical and 12 physical cores
mic-max marked this conversation as resolved.
Show resolved Hide resolved
.NET SDK=6.0.203
[Host] : .NET 6.0.5 (6.0.522.21309), X64 RyuJIT
DefaultJob : .NET 6.0.5 (6.0.522.21309), X64 RyuJIT


| Method | BoundCount | Mean | Error | StdDev | Allocated |
|---------------------------- |----------- |----------:|---------:|---------:|----------:|
| HistogramHotPath | 10 | 45.27 ns | 0.384 ns | 0.359 ns | - |
| HistogramWith1LabelHotPath | 10 | 89.99 ns | 0.373 ns | 0.312 ns | - |
| HistogramWith3LabelsHotPath | 10 | 185.34 ns | 3.184 ns | 3.667 ns | - |
| HistogramWith5LabelsHotPath | 10 | 266.69 ns | 1.391 ns | 1.301 ns | - |
| HistogramWith7LabelsHotPath | 10 | 323.20 ns | 1.834 ns | 1.531 ns | - |
| HistogramHotPath | 20 | 48.69 ns | 0.347 ns | 0.307 ns | - |
| HistogramWith1LabelHotPath | 20 | 93.84 ns | 0.696 ns | 0.651 ns | - |
| HistogramWith3LabelsHotPath | 20 | 189.82 ns | 1.208 ns | 1.071 ns | - |
| HistogramWith5LabelsHotPath | 20 | 269.23 ns | 2.027 ns | 1.693 ns | - |
| HistogramWith7LabelsHotPath | 20 | 329.92 ns | 1.272 ns | 1.128 ns | - |
| HistogramHotPath | 50 | 55.73 ns | 0.339 ns | 0.317 ns | - |
| HistogramWith1LabelHotPath | 50 | 100.38 ns | 0.455 ns | 0.425 ns | - |
| HistogramWith3LabelsHotPath | 50 | 200.02 ns | 1.011 ns | 0.844 ns | - |
| HistogramWith5LabelsHotPath | 50 | 279.94 ns | 1.595 ns | 1.492 ns | - |
| HistogramWith7LabelsHotPath | 50 | 346.88 ns | 1.064 ns | 0.943 ns | - |
| HistogramHotPath | 100 | 66.39 ns | 0.167 ns | 0.148 ns | - |
| HistogramWith1LabelHotPath | 100 | 114.98 ns | 1.340 ns | 1.253 ns | - |
| HistogramWith3LabelsHotPath | 100 | 220.52 ns | 1.723 ns | 1.528 ns | - |
| HistogramWith5LabelsHotPath | 100 | 299.10 ns | 1.950 ns | 1.629 ns | - |
| HistogramWith7LabelsHotPath | 100 | 356.25 ns | 2.153 ns | 1.798 ns | - |
| HistogramHotPath | 10 | 42.68 ns | 0.116 ns | 0.109 ns | - |
| HistogramWith1LabelHotPath | 10 | 89.94 ns | 0.195 ns | 0.173 ns | - |
| HistogramWith3LabelsHotPath | 10 | 175.81 ns | 0.597 ns | 0.558 ns | - |
| HistogramWith5LabelsHotPath | 10 | 259.52 ns | 0.435 ns | 0.363 ns | - |
| HistogramWith7LabelsHotPath | 10 | 316.83 ns | 0.530 ns | 0.470 ns | - |
| HistogramHotPath | 50 | 50.70 ns | 0.356 ns | 0.333 ns | - |
| HistogramWith1LabelHotPath | 50 | 101.23 ns | 0.155 ns | 0.145 ns | - |
| HistogramWith3LabelsHotPath | 50 | 185.92 ns | 0.290 ns | 0.271 ns | - |
| HistogramWith5LabelsHotPath | 50 | 275.40 ns | 0.357 ns | 0.316 ns | - |
| HistogramWith7LabelsHotPath | 50 | 333.33 ns | 0.646 ns | 0.540 ns | - |
| HistogramHotPath | 390 | 115.16 ns | 0.115 ns | 0.108 ns | - |
| HistogramWith1LabelHotPath | 390 | 165.81 ns | 0.378 ns | 0.353 ns | - |
| HistogramWith3LabelsHotPath | 390 | 265.34 ns | 1.043 ns | 0.975 ns | - |
| HistogramWith5LabelsHotPath | 390 | 374.90 ns | 0.938 ns | 0.878 ns | - |
| HistogramWith7LabelsHotPath | 390 | 437.83 ns | 1.014 ns | 0.847 ns | - |
| HistogramHotPath | 410 | 118.25 ns | 0.103 ns | 0.096 ns | - |
| HistogramWith1LabelHotPath | 410 | 171.96 ns | 0.139 ns | 0.130 ns | - |
| HistogramWith3LabelsHotPath | 410 | 269.87 ns | 0.679 ns | 0.635 ns | - |
| HistogramWith5LabelsHotPath | 410 | 355.99 ns | 0.831 ns | 0.778 ns | - |
| HistogramWith7LabelsHotPath | 410 | 421.68 ns | 0.663 ns | 0.587 ns | - |
*/

namespace Benchmarks.Metrics
{
public class HistogramBenchmarks
{
private const int MaxValue = 1000;
private const int MaxValue = 10000;
private readonly Random random = new();
private readonly string[] dimensionValues = new string[] { "DimVal1", "DimVal2", "DimVal3", "DimVal4", "DimVal5", "DimVal6", "DimVal7", "DimVal8", "DimVal9", "DimVal10" };
private Histogram<long> histogram;
private MeterProvider provider;
private Meter meter;
private double[] bounds;

[Params(10, 20, 50, 100)]
[Params(10, 50, 390, 410)]
public int BoundCount { get; set; }

[GlobalSetup]
Expand Down