From 6fea35d1044201013db255d801c6d60fd6582e99 Mon Sep 17 00:00:00 2001 From: Nice3point Date: Sun, 1 Nov 2026 17:55:40 +0300 Subject: [PATCH 1/3] [Build] Update Revit Injector to the latest patch versions --- Directory.Packages.props | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index c4410a3..f7d103d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -13,13 +13,13 @@ - - - - - - - + + + + + + + From 357e7b3c37bef190eec110075a110983655f3e41 Mon Sep 17 00:00:00 2001 From: Nice3point Date: Sun, 1 Nov 2026 17:55:40 +0300 Subject: [PATCH 2/3] [Benchmarks] Start the profiler attach thread in .NET Framework benchmark processes --- CHANGELOG.md | 1 + .../Hosting/BenchmarkHostProcess.cs | 19 +++++++++++++ .../Hosting/ProfilerAttachThread.cs | 28 +++++++++++++++++++ .../Hosting/RevitUiMetadataResolver.cs | 3 +- .../RevitApplicationBenchmark.cs | 2 ++ 5 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 source/Nice3point.BenchmarkDotNet.Revit/Hosting/BenchmarkHostProcess.cs create mode 100644 source/Nice3point.BenchmarkDotNet.Revit/Hosting/ProfilerAttachThread.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 07eb1ce..0860ea4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ UI benchmarks use the `RevitAPIUI` types, add the `Nice3point.Revit.Api.RevitAPI - A benchmark project that references `RevitAPIUI` runs without `FileNotFoundException` https://github.com/Nice3point/RevitBenchmark/issues/57. - After a run of `RevitApiUiBenchmark` benchmarks, Revit opens its window at the position, the size, and the maximized state it had before the run. +- The dotTrace profiler attaches to the process of a `RevitApiBenchmark` benchmark https://github.com/Nice3point/RevitBenchmark/issues/64. # 2027.0.1 diff --git a/source/Nice3point.BenchmarkDotNet.Revit/Hosting/BenchmarkHostProcess.cs b/source/Nice3point.BenchmarkDotNet.Revit/Hosting/BenchmarkHostProcess.cs new file mode 100644 index 0000000..4f97c2a --- /dev/null +++ b/source/Nice3point.BenchmarkDotNet.Revit/Hosting/BenchmarkHostProcess.cs @@ -0,0 +1,19 @@ +using System.Reflection; + +namespace Nice3point.BenchmarkDotNet.Revit.Hosting; + +/// +/// Provides the facts about the BenchmarkDotNet host process. +/// +internal static class BenchmarkHostProcess +{ + private const string GeneratedProgramTypeName = "BenchmarkDotNet.Autogenerated.UniqueProgramName"; + + /// + /// Gets a value indicating whether the current process is the BenchmarkDotNet host process. + /// + /// + /// in a benchmark process that runs a generated program, and inside Revit. + /// + public static bool IsCurrent { get; } = Assembly.GetEntryAssembly() is { } entryAssembly && entryAssembly.GetType(GeneratedProgramTypeName) is null; +} diff --git a/source/Nice3point.BenchmarkDotNet.Revit/Hosting/ProfilerAttachThread.cs b/source/Nice3point.BenchmarkDotNet.Revit/Hosting/ProfilerAttachThread.cs new file mode 100644 index 0000000..b10884e --- /dev/null +++ b/source/Nice3point.BenchmarkDotNet.Revit/Hosting/ProfilerAttachThread.cs @@ -0,0 +1,28 @@ +namespace Nice3point.BenchmarkDotNet.Revit.Hosting; + +/// +/// Starts the profiler attach thread of the .NET Framework runtime in every benchmark process. +/// +/// +/// A .NET Framework benchmark process with Revit answers a profiler attach request only on the attach thread. +/// The runtime reads the setting when it starts. +/// A benchmark process inherits the setting from the BenchmarkDotNet host process. +/// +internal static class ProfilerAttachThread +{ + /// + /// Enables the profiler attach thread for the benchmark processes the host process starts. + /// + /// + /// The call has no effect outside the BenchmarkDotNet host process and on .NET. + /// + public static void Enable() + { +#if NETFRAMEWORK + if (BenchmarkHostProcess.IsCurrent) + { + Environment.SetEnvironmentVariable("COMPlus_AttachThreadAlwaysOn", "1"); + } +#endif + } +} diff --git a/source/Nice3point.BenchmarkDotNet.Revit/Hosting/RevitUiMetadataResolver.cs b/source/Nice3point.BenchmarkDotNet.Revit/Hosting/RevitUiMetadataResolver.cs index 17cbb4c..b0be316 100644 --- a/source/Nice3point.BenchmarkDotNet.Revit/Hosting/RevitUiMetadataResolver.cs +++ b/source/Nice3point.BenchmarkDotNet.Revit/Hosting/RevitUiMetadataResolver.cs @@ -19,7 +19,6 @@ namespace Nice3point.BenchmarkDotNet.Revit.Hosting; internal static class RevitUiMetadataResolver { private const string AssemblyName = "RevitAPIUI"; - private const string GeneratedProgramTypeName = "BenchmarkDotNet.Autogenerated.UniqueProgramName"; // IMAGE_COR20_HEADER offsets. private const int CorFlagsOffset = 16; @@ -57,7 +56,7 @@ internal static class RevitUiMetadataResolver /// public static void Register() { - if (Assembly.GetEntryAssembly() is not { } entryAssembly || entryAssembly.GetType(GeneratedProgramTypeName) is not null) + if (!BenchmarkHostProcess.IsCurrent) { return; } diff --git a/source/Nice3point.BenchmarkDotNet.Revit/RevitApplicationBenchmark.cs b/source/Nice3point.BenchmarkDotNet.Revit/RevitApplicationBenchmark.cs index 3cdc48e..1122dd7 100644 --- a/source/Nice3point.BenchmarkDotNet.Revit/RevitApplicationBenchmark.cs +++ b/source/Nice3point.BenchmarkDotNet.Revit/RevitApplicationBenchmark.cs @@ -32,6 +32,7 @@ public abstract class RevitApplicationBenchmark /// The runtime calls the method once per process, when the module loads. /// The method sets the STA apartment state of the current thread and initializes the injector. /// In the BenchmarkDotNet host process, the method registers the resolver of the RevitAPIUI metadata. + /// On .NET Framework, the host process enables the profiler attach thread of the benchmark processes. /// Inside Revit, the method has no effect. /// #pragma warning disable CA2255 @@ -49,6 +50,7 @@ public static void Initialize() Thread.CurrentThread.SetApartmentState(ApartmentState.STA); RevitUiMetadataResolver.Register(); + ProfilerAttachThread.Enable(); InjectorInitializer.InitializeModule(); } From e8f333cb96aa033f39d98327cd7f034b1c422870 Mon Sep 17 00:00:00 2001 From: Nice3point Date: Sun, 1 Nov 2026 18:29:55 +0300 Subject: [PATCH 3/3] [Docs] Remove the dotTrace entry from the bug fixes --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0860ea4..07eb1ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,7 +44,6 @@ UI benchmarks use the `RevitAPIUI` types, add the `Nice3point.Revit.Api.RevitAPI - A benchmark project that references `RevitAPIUI` runs without `FileNotFoundException` https://github.com/Nice3point/RevitBenchmark/issues/57. - After a run of `RevitApiUiBenchmark` benchmarks, Revit opens its window at the position, the size, and the maximized state it had before the run. -- The dotTrace profiler attaches to the process of a `RevitApiBenchmark` benchmark https://github.com/Nice3point/RevitBenchmark/issues/64. # 2027.0.1