Added a benchmark project for StartupLogger's `SetStartupLogFilePath` (#2067)

This commit is contained in:
xiang17 2023-01-25 21:32:16 -08:00 committed by GitHub
parent 441e043cb2
commit 622e437541
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 179 additions and 45 deletions

View File

@ -153,6 +153,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApplication.MultipleApp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApplication.Quartz", "test\test-applications\integrations\TestApplication.Quartz\TestApplication.Quartz.csproj", "{B48780CE-8AAB-44D3-9CD1-8491584352B5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "test\Benchmarks\Benchmarks.csproj", "{B1E71654-E784-4A39-BE45-8671E027B6D7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApplication.EntityFrameworkCore", "test\test-applications\integrations\TestApplication.EntityFrameworkCore\TestApplication.EntityFrameworkCore.csproj", "{036A56A4-4EEF-42E3-9857-B9B00D302BF9}"
EndProject
Global
@ -723,6 +725,18 @@ Global
{B48780CE-8AAB-44D3-9CD1-8491584352B5}.Release|x64.Build.0 = Release|x64
{B48780CE-8AAB-44D3-9CD1-8491584352B5}.Release|x86.ActiveCfg = Release|x86
{B48780CE-8AAB-44D3-9CD1-8491584352B5}.Release|x86.Build.0 = Release|x86
{B1E71654-E784-4A39-BE45-8671E027B6D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B1E71654-E784-4A39-BE45-8671E027B6D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B1E71654-E784-4A39-BE45-8671E027B6D7}.Debug|x64.ActiveCfg = Debug|Any CPU
{B1E71654-E784-4A39-BE45-8671E027B6D7}.Debug|x64.Build.0 = Debug|Any CPU
{B1E71654-E784-4A39-BE45-8671E027B6D7}.Debug|x86.ActiveCfg = Debug|Any CPU
{B1E71654-E784-4A39-BE45-8671E027B6D7}.Debug|x86.Build.0 = Debug|Any CPU
{B1E71654-E784-4A39-BE45-8671E027B6D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B1E71654-E784-4A39-BE45-8671E027B6D7}.Release|Any CPU.Build.0 = Release|Any CPU
{B1E71654-E784-4A39-BE45-8671E027B6D7}.Release|x64.ActiveCfg = Release|Any CPU
{B1E71654-E784-4A39-BE45-8671E027B6D7}.Release|x64.Build.0 = Release|Any CPU
{B1E71654-E784-4A39-BE45-8671E027B6D7}.Release|x86.ActiveCfg = Release|Any CPU
{B1E71654-E784-4A39-BE45-8671E027B6D7}.Release|x86.Build.0 = Release|Any CPU
{036A56A4-4EEF-42E3-9857-B9B00D302BF9}.Debug|Any CPU.ActiveCfg = Debug|x64
{036A56A4-4EEF-42E3-9857-B9B00D302BF9}.Debug|Any CPU.Build.0 = Debug|x64
{036A56A4-4EEF-42E3-9857-B9B00D302BF9}.Debug|x64.ActiveCfg = Debug|x64
@ -791,6 +805,7 @@ Global
{5FDB5603-21D3-446A-8B50-36DACCF7C2FF} = {E409ADD3-9574-465C-AB09-4324D205CC7C}
{A0338846-2AF8-4D96-ADA7-EBD4F010D08F} = {E409ADD3-9574-465C-AB09-4324D205CC7C}
{B48780CE-8AAB-44D3-9CD1-8491584352B5} = {E409ADD3-9574-465C-AB09-4324D205CC7C}
{B1E71654-E784-4A39-BE45-8671E027B6D7} = {5C915382-C886-457D-8641-9E766D8E5A17}
{036A56A4-4EEF-42E3-9857-B9B00D302BF9} = {E409ADD3-9574-465C-AB09-4324D205CC7C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution

View File

@ -150,6 +150,17 @@ partial class Build
}
});
Target CompileBenchmarks => _ => _
.Description("Compiles the Benchmarks project in the test directory")
.After(CompileManagedSrc)
.Executes(() =>
{
DotNetBuild(x => x
.SetProjectFile(Solution.GetBenchmarks())
.SetConfiguration(BuildConfiguration)
.EnableNoRestore());
});
Target CompileNativeSrc => _ => _
.Description("Compiles the native loader")
.DependsOn(CompileNativeSrcWindows)

View File

@ -77,7 +77,8 @@ partial class Build : NukeBuild
.DependsOn(BuildTracer)
.DependsOn(CompileExamples)
.DependsOn(NativeTests)
.DependsOn(ManagedTests);
.DependsOn(ManagedTests)
.DependsOn(CompileBenchmarks);
Target BuildTracer => _ => _
.Description("Builds the native and managed src, and publishes the tracer home directory")

View File

@ -12,6 +12,11 @@ public static class Projects
public const string AutoInstrumentationMock = "OpenTelemetry.AutoInstrumentation.Mock";
}
public static class Benchmarks
{
public const string AutoInstrumentationBenchmarks = "Benchmarks";
}
public static class Tests
{
public const string AutoInstrumentationNativeTests = "OpenTelemetry.AutoInstrumentation.Native.Tests";

View File

@ -72,6 +72,11 @@ public static class ProjectsHelper
return solution.GetProject(Projects.Mocks.AutoInstrumentationMock);
}
public static Project GetBenchmarks(this Solution solution)
{
return solution.GetProject(Projects.Benchmarks.AutoInstrumentationBenchmarks);
}
public static IEnumerable<Project> GetWindowsOnlyTestApplications(this Solution solution)
{
return solution
@ -96,7 +101,8 @@ public static class ProjectsHelper
return solution.GetManagedSrcProjects()
.Concat(solution.GetManagedTestProjects())
.Concat(solution.GetCrossPlatformTestApplications())
.Concat(new[] { solution.GetTestMock() });
.Concat(new[] { solution.GetTestMock() })
.Concat(new[] { solution.GetBenchmarks() });
}
public static IEnumerable<Project> GetNativeProjects(this Solution solution)

View File

@ -16,4 +16,5 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Benchmarks")]
[assembly: InternalsVisibleTo("OpenTelemetry.AutoInstrumentation.Loader.Tests")]

View File

@ -77,6 +77,49 @@ internal static class StartupLogger
}
}
internal static string? SetStartupLogFilePath()
{
if (LogDirectory == null)
{
return null;
}
try
{
// Pick up the parts used to build the log file name and minimize the chances
// of file name conflict with other processes.
using var process = Process.GetCurrentProcess();
// AppDomain friendly name can contain characters that are invalid in file names,
// remove any of those. For the first assembly loaded by the process this is typically
// expected to be name of the file with the application entry point.
var appDomainFriendlyName = AppDomain.CurrentDomain.FriendlyName;
var invalidChars = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
var sb = new StringBuilder(appDomainFriendlyName);
for (int i = 0; i < sb.Length; i++)
{
if (invalidChars.IndexOf(sb[i]) != -1)
{
sb[i] = '_';
}
}
appDomainFriendlyName = sb.ToString();
// AppDomain friendly name may not be unique in the same process, use also the id.
// Per documentation the id is an integer that uniquely identifies the application
// domain within the process.
var appDomainId = AppDomain.CurrentDomain.Id;
return Path.Combine(LogDirectory, $"otel-dotnet-auto-loader-{appDomainFriendlyName}-{appDomainId}-{process?.Id}.log");
}
catch
{
// We can't get the process info
return Path.Combine(LogDirectory, $"otel-dotnet-auto-loader-{Guid.NewGuid()}.log");
}
}
private static string? GetLogDirectory()
{
string? logDirectory = null;
@ -131,49 +174,6 @@ internal static class StartupLogger
}
}
private static string? SetStartupLogFilePath()
{
if (LogDirectory == null)
{
return null;
}
try
{
// Pick up the parts used to build the log file name and minimize the chances
// of file name conflict with other processes.
using var process = Process.GetCurrentProcess();
// AppDomain friendly name can contain characters that are invalid in file names,
// remove any of those. For the first assembly loaded by the process this is typically
// expected to be name of the file with the application entry point.
var appDomainFriendlyName = AppDomain.CurrentDomain.FriendlyName;
var invalidChars = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
var sb = new StringBuilder(appDomainFriendlyName);
for (int i = 0; i < sb.Length; i++)
{
if (invalidChars.IndexOf(sb[i]) != -1)
{
sb[i] = '_';
}
}
appDomainFriendlyName = sb.ToString();
// AppDomain friendly name may not be unique in the same process, use also the id.
// Per documentation the id is an integer that uniquely identifies the application
// domain within the process.
var appDomainId = AppDomain.CurrentDomain.Id;
return Path.Combine(LogDirectory, $"otel-dotnet-auto-loader-{appDomainFriendlyName}-{appDomainId}-{process?.Id}.log");
}
catch
{
// We can't get the process info
return Path.Combine(LogDirectory, $"otel-dotnet-auto-loader-{Guid.NewGuid()}.log");
}
}
private static FileSink? SetLogFileSink()
{
if (StartupLogFilePath == null)

View File

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\OpenTelemetry.AutoInstrumentation.Loader\OpenTelemetry.AutoInstrumentation.Loader.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- This file prevents unintended imports of unrelated MSBuild files -->
<!-- Uncomment to include parent Directory.Build.props file -->
<!--<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />-->
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,24 @@
// <copyright file="Program.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using BenchmarkDotNet.Running;
namespace OpenTelemetry.AutoInstrumentation.Loader.Benchmarks;
internal class Program
{
private static void Main(string[] args) => BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
}

View File

@ -0,0 +1,42 @@
// <copyright file="StartupLoggerBenchmarks.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using BenchmarkDotNet.Attributes;
/*
BenchmarkDotNet=v0.13.4, OS=Windows 11 (10.0.22621.1105)
Intel Core i9-10900K CPU 3.70GHz, 1 CPU, 20 logical and 10 physical cores
.NET SDK=7.0.200-preview.22628.1
[Host] : .NET 6.0.13 (6.0.1322.58009), X64 RyuJIT AVX2
DefaultJob : .NET 6.0.13 (6.0.1322.58009), X64 RyuJIT AVX2
| Method | Mean | Error | StdDev | Gen0 | Allocated |
|---------------------- |---------:|----------:|----------:|-------:|----------:|
| SetStartupLogFilePath | 1.458 us | 0.0133 us | 0.0111 us | 0.2136 | 2.19 KB |
*/
namespace OpenTelemetry.AutoInstrumentation.Loader.Benchmarks;
[MemoryDiagnoser]
public class StartupLoggerBenchmarks
{
[Benchmark]
public void SetStartupLogFilePath()
{
var path = StartupLogger.SetStartupLogFilePath();
}
}

View File

@ -2,6 +2,7 @@
<Import Project="..\Directory.Packages.props" />
<ItemGroup>
<PackageVersion Include="BenchmarkDotNet" Version="0.13.4" />
<PackageVersion Include="Elastic.Clients.Elasticsearch" Version="8.0.0" />
<PackageVersion Include="FluentAssertions" Version="6.9.0" />
<PackageVersion Include="Google.Protobuf" Version="3.21.12" />