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

[Exporter.OTLP] Optimize GetHeaders by Spans #6179

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

nimanikoo
Copy link

@nimanikoo nimanikoo commented Mar 8, 2025

Title: Optimize header parsing in GetHeaders method by replacing Split with Span to enhance performance and reduce allocations. OtlpExporterOptionsExtensions.cs

Design discussion issue: 6180
#6180

Changes

Refactored the GetHeaders method to utilize Span<T> for parsing header strings, aiming to improve performance by minimizing memory allocations. This change is inspired by techniques discussed in the following articles:

By implementing these optimizations, I hope to contribute to the project's performance enhancements and am eager to assist further in its development.

Merge requirement checklist

…thod and reducing allocations. OtlpExporterOptionsExtensions.cs
@nimanikoo nimanikoo requested a review from a team as a code owner March 8, 2025 19:23
Copy link

linux-foundation-easycla bot commented Mar 8, 2025

CLA Signed

The committers listed above are authorized under a signed CLA.

@github-actions github-actions bot added the pkg:OpenTelemetry.Exporter.OpenTelemetryProtocol Issues related to OpenTelemetry.Exporter.OpenTelemetryProtocol NuGet package label Mar 8, 2025
@rajkumar-rangaraj
Copy link
Contributor

@nimanikoo Could you please add a benchmark to measure performance improvement?

@nimanikoo
Copy link
Author

@rajkumar-rangaraj

Sure! I’ll add a benchmark to measure the performance improvement.

I’ll use BenchmarkDotNet to compare the old and new implementations of GetHeaders. The benchmark will measure execution time and memory allocations to demonstrate the benefits of using Span.

I’ll update the PR soon with the benchmark results. Thanks for the suggestion!

@nimanikoo
Copy link
Author

nimanikoo commented Mar 8, 2025

@rajkumar-rangaraj I benchmarked two implementations of the GetHeaders method—GetHeadersOld and GetHeadersNew—to evaluate the impact of code optimization.

System Specifications:

  • Operating System: Linux Mint 21.3
  • Processor: Intel Core i5-10300H CPU 2.50GHz
  • .NET SDK: 8.0.112
  • Kernel: 5.15.0-127-generic

Benchmark Results:

Method Mean Error StdDev Ratio
GetHeadersOld 353.7 ns 1.69 ns 1.41 ns 1.00
GetHeadersNew 226.5 ns 0.32 ns 0.30 ns 0.64

These results indicate that GetHeadersNew performs 36% faster than GetHeadersOld. This improvement is likely due to optimizations such as utilizing Span<T> for more efficient memory handling.

benchmark

@nimanikoo
Copy link
Author

I modified only GetHeaders method, making changes inside the method without altering its input parameters or return result. However, I'm unable to identify the issue causing the tests and build to fail. Could you please help me in resolving this?

@rajkumar-rangaraj

@rajkumar-rangaraj
Copy link
Contributor

I modified only GetHeaders method, making changes inside the method without altering its input parameters or return result. However, I'm unable to identify the issue causing the tests and build to fail. Could you please help me in resolving this?

@rajkumar-rangaraj

In your local development environment, performing a release build should reveal these errors. Here are the errors from CI:

Error: D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OtlpExporterOptionsExtensions.cs(52,1): error SA1137: Elements should have the same indentation (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1137.md) [D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj::TargetFramework=net462]
Error: D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OtlpExporterOptionsExtensions.cs(96,1): error SA1507: Code should not contain multiple blank lines in a row (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1507.md) [D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj::TargetFramework=net8.0]
Error: D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OtlpExporterOptionsExtensions.cs(96,1): error SA1507: Code should not contain multiple blank lines in a row (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1507.md) [D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj::TargetFramework=net462]
Error: D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OtlpExporterOptionsExtensions.cs(52,1): error SA1137: Elements should have the same indentation (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1137.md) [D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj::TargetFramework=net8.0]
Error: D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OtlpExporterOptionsExtensions.cs(52,1): error SA1137: Elements should have the same indentation (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1137.md) [D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj::TargetFramework=net9.0]
Error: D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OtlpExporterOptionsExtensions.cs(96,1): error SA1507: Code should not contain multiple blank lines in a row (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1507.md) [D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj::TargetFramework=net9.0]
Error: D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OtlpExporterOptionsExtensions.cs(52,1): error SA1137: Elements should have the same indentation (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1137.md) [D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj::TargetFramework=netstandard2.0]
Error: D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OtlpExporterOptionsExtensions.cs(96,1): error SA1507: Code should not contain multiple blank lines in a row (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1507.md) [D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj::TargetFramework=netstandard2.0]
Error: D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OtlpExporterOptionsExtensions.cs(52,1): error SA1137: Elements should have the same indentation (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1137.md) [D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj::TargetFramework=netstandard2.1]
Error: D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OtlpExporterOptionsExtensions.cs(96,1): error SA1507: Code should not contain multiple blank lines in a row (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1507.md) [D:\a\opentelemetry-dotnet\opentelemetry-dotnet\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj::TargetFramework=netstandard2.1]

@nimanikoo
Copy link
Author

Ah, I figured out what the problem was.
Thank you, I'll fix it.
I thought there was a critical problem that would interfere with the project.

- Ensure consistent indentation to comply with StyleCop rule SA1137.
- Remove multiple consecutive blank lines to comply with StyleCop rule SA1507.
@nimanikoo
Copy link
Author

I've tried to fix all the indentation issues mentioned by the code analyzer. Is there anything else I should fix?
Thank you for your help and the time you’re putting into this.
@rajkumar-rangaraj

@Kielek Kielek changed the title Refactor code to use Span<T> for header parsing, eliminating Split me… [Exporter.OTLP] Optimize GetHeaders by Spans Mar 11, 2025
Copy link
Contributor

@Kielek Kielek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with minor improvement and one direct build fix.

throw new ArgumentException("Headers provided in an invalid format.");
}
pair = headersSpan;
headersSpan = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
headersSpan = [];
headersSpan = ReadOnlySpan<char>.Empty;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? The [] is the recommended way by the analyzers. IDE0300/IDE0301 as I remember?

@xiang17
Copy link
Contributor

xiang17 commented Mar 11, 2025

The benchmarks results look good. However, it doesn't have any memory related stats. Can you run with the -m option to enables MemoryDiagnoser and prints memory statistics.

@xiang17
Copy link
Contributor

xiang17 commented Mar 12, 2025

How much code coverage do the existing unit test cases have for this method? Since the sole purpose of this PR is to update the parse logic, it might be good to add more test cases.

Can you also include the benchmark code in the PR description or somewhere in the comment? No need to include it in the code change.

@nimanikoo
Copy link
Author

nimanikoo commented Mar 12, 2025

Based on the references used by this method, I’ve run benchmarks in two different scenarios with the same conditions and system as mentioned in the previous comments, and this is the result. Do you think any further changes are needed or is there anything else I should do?
@xiang17
#2 OtlpHttpExporterBenchmarks

old code

oltphttpexporter_Old

new code

oltphttpexporeter_refactor

@nimanikoo nimanikoo requested a review from xiang17 March 12, 2025 01:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg:OpenTelemetry.Exporter.OpenTelemetryProtocol Issues related to OpenTelemetry.Exporter.OpenTelemetryProtocol NuGet package
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants