You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
BenchmarkDotNet supports [NativeAOT](https://github.com/dotnet/runtime/tree/main/src/coreclr/nativeaot/docs)! However, you might want to know how it works to get a better understanding of the results that you get.
193
+
BenchmarkDotNet supports [NativeAOT](https://github.com/dotnet/runtime/tree/main/src/coreclr/nativeaot)! However, you might want to know how it works to get a better understanding of the results that you get.
194
194
195
-
* NativeAOT is a flavor of .NET Core. Which means that:
196
-
* you have to target .NET Core to be able to build NativeAOT benchmarks (example: `<TargetFramework>net7.0</TargetFramework>` in the .csproj file)
197
-
* you have to specify the NativeAOT runtime in an explicit way, either by using `[SimpleJob]` attribute or by using the fluent Job config API `Job.ShortRun.With(NativeAotRuntime.$version)` or console line arguments `--runtimes nativeaot7.0`
198
-
* to run NativeAOT benchmark you run the app as a .NET Core/.NET process (example: `dotnet run -c Release -f net5.01`) and BenchmarkDotNet does all the NativeAOT compilation for you. If you want to check what files are generated you need to apply `[KeepBenchmarkFiles]` attribute to the class which defines benchmarks.
195
+
As every AOT solution, NativeAOT has some [limitations](https://github.com/dotnet/runtime/blob/main/src/coreclr/nativeaot/docs/limitations.md) like limited reflection support or lack of dynamic assembly loading. Because of that, the host process (what you run from command line) is never an AOT process, but just a regular .NET process. This process (called Host process) uses reflection to read benchmarks metadata (find all `[Benchmark]` methods etc), generates a new project that references the benchmarks and compiles it using ILCompiler. Such compilation produces a native executable, which is later started by the Host process. This process (called Benchmark or Child process) performs the actual benchmarking and reports the results back to the Host process. By default BenchmarkDotNet uses the latest version of `Microsoft.DotNet.ILCompiler` to build the NativeAOT benchmark according to [this instructions](https://github.com/dotnet/runtime/blob/main/src/coreclr/nativeaot/docs/compiling.md).
199
196
200
-
By default BenchmarkDotNet uses the latest version of `Microsoft.DotNet.ILCompiler` to build the NativeAOT benchmark according to [this instructions](https://github.com/dotnet/runtime/blob/main/src/coreclr/nativeaot/docs/compiling.md).
197
+
This is why you need to:
198
+
- install [pre-requisites](https://github.com/dotnet/runtime/blob/main/src/coreclr/nativeaot/docs/prerequisites.md) required by NativeAOT compiler
199
+
- target .NET to be able to run NativeAOT benchmarks (example: `<TargetFramework>net7.0</TargetFramework>` in the .csproj file)
200
+
- run the app as a .NET process (example: `dotnet run -c Release -f net7.0`).
201
+
- specify the NativeAOT runtime in an explicit way, either by using console line arguments `--runtimes nativeaot7.0` (the recommended approach), or by using`[SimpleJob]` attribute or by using the fluent Job config API `Job.ShortRun.With(NativeAotRuntime.Net70)`:
202
+
203
+
```cmd
204
+
dotnet run -c Release -f net7.0 --runtimes nativeaot7.0
205
+
```
206
+
207
+
or:
201
208
202
209
```cs
203
210
varconfig=DefaultConfig.Instance
@@ -208,6 +215,8 @@ BenchmarkSwitcher
208
215
.Run(args, config);
209
216
```
210
217
218
+
or:
219
+
211
220
```cs
212
221
[SimpleJob(RuntimeMoniker.NativeAot70)] // compiles the benchmarks as net7.0 and uses the latest NativeAOT to build a native app
213
222
publicclassTheTypeWithBenchmarks
@@ -216,7 +225,7 @@ public class TheTypeWithBenchmarks
216
225
}
217
226
```
218
227
219
-
**Note**: BenchmarkDotNet is going to run `dotnet restore` on the auto-generated project. The first time it does so, it's going to take a **LOT** of time to download all the dependencies (few minutes). Just give it some time and don't press `Ctrl+C` too fast ;)
228
+
### Customization
220
229
221
230
If you want to benchmark some particular version of NativeAOT (or from a different NuGet feed) you have to specify it in an explicit way:
222
231
@@ -228,45 +237,119 @@ var config = DefaultConfig.Instance
228
237
microsoftDotNetILCompilerVersion: "7.0.0-*", // the version goes here
229
238
nuGetFeedUrl: "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json") // this address might change over time
230
239
.DisplayName("NativeAOT NuGet")
231
-
.TargetFrameworkMoniker("net5.0")
240
+
.TargetFrameworkMoniker("net7.0")
232
241
.ToToolchain()));
233
242
```
234
243
244
+
The builder allows to configure more settings:
245
+
- specify packages restore path by using `PackagesRestorePath($path)`
246
+
- rooting all application assemblies by using `RootAllApplicationAssemblies($bool)`. This is disabled by default.
247
+
- generating complete type metadata by using `IlcGenerateCompleteTypeMetadata($bool)`. This option is enabled by default.
248
+
- generating stack trace metadata by using `IlcGenerateStackTraceData($bool)`. This option is enabled by default.
249
+
- set optimization preference by using `IlcOptimizationPreference($value)`. The default is `Speed`, you can configure it to `Size` or nothing
250
+
- set instruction set for the target OS, architecture and hardware by using `IlcInstructionSet($value)`. By default BDN recognizes most of the instruction sets on your machine and enables them.
251
+
252
+
BenchmarkDotNet supports [rd.xml](https://github.com/dotnet/runtime/blob/main/src/coreclr/nativeaot/docs/rd-xml-format.md) files. To get given file respected by BenchmarkDotNet you need to place it in the same folder as the project that defines benchmarks and name it `rd.xml` or in case of multiple files give them `.rd.xml` extension. The alternative to `rd.xml` files is annotating types with [DynamicallyAccessedMembers](https://devblogs.microsoft.com/dotnet/app-trimming-in-net-5/) attribute.
253
+
254
+
If given benchmark is not supported by NativeAOT, you need to apply `[AotFilter]` attribute for it. Example:
By default BenchmarkDotNet removes the generates files after finishing the run. To keep them on the disk you need to pass `--keepFiles true` command line argument or apply `[KeepBenchmarkFiles]` attribute to the class which defines benchmark(s). Then, read the folder from the tool output. In the example below it's `D:\projects\performance\artifacts\bin\MicroBenchmarks\Release\net7.0\Job-KRLVKQ`:
265
+
266
+
```log
267
+
// ***** Building 1 exe(s) in Parallel: Start *****
If you go to `D:\projects\performance\artifacts\bin\MicroBenchmarks\Release\net7.0\Job-KRLVKQ`, you can see the generated project file (named `BenchmarkDotNet.Autogenerated.csproj`), code (file name ends with `.notcs`) and find the native executable (in the `bin\**\native` subfolder). Example:
275
+
276
+
```cmd
277
+
cd D:\projects\performance\artifacts\bin\MicroBenchmarks\Release\net7.0\Job-KRLVKQ
### Compiling source to native code using the ILCompiler you built
236
327
237
-
If you are a NativeAOT contributor and you want to benchmark your local build of NativeAOT you have to provide necessary info (IlcPath):
328
+
If you are a NativeAOT contributor and you want to benchmark your local build of NativeAOT you have to provide necessary info (path to shipping packages).
329
+
330
+
You can do that from command line:
331
+
332
+
```cmd
333
+
dotnet run -c Release -f net7.0 --runtimes nativeaot7.0 --ilcPackages D:\projects\runtime\artifacts\packages\Release\Shipping\
BenchmarkDotNet is going to follow [these instructrions](https://github.com/dotnet/corert/blob/7f902d4d8b1c3280e60f5e06c71951a60da173fb/Documentation/how-to-build-and-run-ilcompiler-in-console-shell-prompt.md#compiling-source-to-native-code-using-the-ilcompiler-you-built) to get it working for you.
250
-
251
-
### Using CPP Code Generator
252
-
253
-
> This approach uses transpiler to convert IL to C++, and then uses platform specific C++ compiler and linker for compiling/linking the application. The transpiler is a lot less mature than the RyuJIT path. If you came here to give CoreRT a try on your .NET Core program, use the RyuJIT option above.
349
+
BenchmarkDotNet is going to follow [these instructrions](https://github.com/dotnet/runtime/blob/main/docs/workflow/building/coreclr/nativeaot.md#building) to get it working for you.
254
350
255
-
If you want to test [CPP Code Generator](https://github.com/dotnet/corert/blob/7f902d4d8b1c3280e60f5e06c71951a60da173fb/Documentation/how-to-build-and-run-ilcompiler-in-console-shell-prompt.md#using-cpp-code-generator) you have to use `UseCppCodeGenerator` method:
**Note**: BenchmarkDotNet is going to run `dotnet restore` on the auto-generated project and restore the packages to a temporary folder. It might take some time, but the next time you rebuild dotnet/runtime repo and run the same command BenchmarkDotNet is going to use the new ILCompiler package.
268
352
269
-
**Note**: You might get some `The method or operation is not implemented.` errors as of today if the code that you are trying to benchmark is using some features that are not implemented by NativeAOT/transpiler yet...
0 commit comments