https://github.com/whiteblackgoose/codegenanalysis
Library for obtaining and analyzing the codegen of JIT for .NET. Can be used for both tests (assertions) and making reports (benchmarks).
https://github.com/whiteblackgoose/codegenanalysis
codegen dotnet jit performance performance-analysis
Last synced: about 1 year ago
JSON representation
Library for obtaining and analyzing the codegen of JIT for .NET. Can be used for both tests (assertions) and making reports (benchmarks).
- Host: GitHub
- URL: https://github.com/whiteblackgoose/codegenanalysis
- Owner: WhiteBlackGoose
- License: mit
- Created: 2021-11-16T13:07:18.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2022-12-04T19:29:10.000Z (over 3 years ago)
- Last Synced: 2025-07-06T14:03:13.567Z (about 1 year ago)
- Topics: codegen, dotnet, jit, performance, performance-analysis
- Language: C#
- Homepage:
- Size: 252 KB
- Stars: 24
- Watchers: 4
- Forks: 0
- Open Issues: 8
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# CodegenAnalysis





Library for analyzing the machine code generated by JIT (codegen). Has API for obtaining the codegen, verifying the characteristics for tests (in a similar manner to xUnit), and generating reports as benchmarks (in a similar manner to BenchmarkDotNet). Supports x86_64 on three major platforms (Windows, MacOS, Linux).
## Why should I use it?
First of all, most .NET developers don't need this library. If you want to measure performance of your code, use [BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet).
If you're working on low-level, often HW-related project, where it's crucial if a branch or call or etc. is optimized or not, this library is for you.
### Table of contents
- [CodegenAnalysis](#CodegenAnalysis)
- [CodegenAnalysis.Assertions](#CodegenAnalysisAssertions)
- [CodegenAnalysis.Benchmarks](#CodegenAnalysisBenchmarks)
## CodegenAnalysis
[](https://www.nuget.org/packages/CodegenAnalysis)
```cs
static int AddAndMul(int a, int b) => a + b * a;
...
var ci = CodegenInfo.Obrain(() => AddAndMul(3, 5));
Console.WriteLine(ci);
```
Output:
```assembly
00007FFD752E42F0 8BC2 mov eax,edx
00007FFD752E42F2 0FAFC1 imul eax,ecx
00007FFD752E42F5 03C1 add eax,ecx
00007FFD752E42F7 C3 ret
```
## CodegenAnalysis.Assertions
[](https://www.nuget.org/packages/CodegenAnalysis.Assertions)
### Verifying the size of the codegen
```cs
using CodegenAssertions;
using Xunit;
public class CodegenSizeTest
{
public static int SomeMethod(int a, int b)
=> a + b;
[Fact]
public void Test1()
{
CodegenInfo.Obtain(() => SomeMethod(4, 5), CompilationTier.Tier1)
.ShouldBeNotLargerThan(20);
}
}
```
### Having calls in the codegen
```cs
public class Tests
{
public class A
{
public virtual int H => 3;
}
public sealed class B : A
{
public override int H => 6;
}
// this will get devirtualized at tier1, but not at tier0
static int Twice(B b) => b.H * 2;
[Fact]
public void NotDevirtTier0()
{
CodegenInfo.Obtain(() => Twice(new B()), CompilationTier.Default)
.ShouldHaveCalls(c => c >= 1);
}
[Fact]
public void DevirtTier1()
{
CodegenInfo.Obtain(() => Twice(new B()), CompilationTier.Tier1)
.ShouldHaveCalls(0);
}
}
```
### Testing if we have branches
```cs
private static readonly bool True = true;
static int SmartThing()
{
if (True)
return 5;
return 10;
}
[Fact]
public void BranchElimination()
{
CodegenInfo.Obtain(() => SmartThing())
.ShouldHaveBranches(0);
}
[MethodImpl(MethodImplOptions.NoOptimization)]
static int StupidThing()
{
if (True)
return 5;
return 10;
}
[Fact]
public void NoBranchElimination()
{
CodegenInfo.Obtain(() => StupidThing(), CompilationTier.Default)
.ShouldHaveBranches(b => b > 0);
}
```
## CodegenAnalysis.Benchmarks
[](https://www.nuget.org/packages/CodegenAnalysis.Benchmarks)
```cs
CodegenBenchmarkRunner.Run();
[CAJob(Tier = CompilationTier.Default),
CAJob(Tier = CompilationTier.Tier1)]
[CAColumn(CAColumn.Branches),
CAColumn(CAColumn.Calls),
CAColumn(CAColumn.CodegenSize),
CAColumn(CAColumn.StaticStackAllocations)]
[CAExport(Export.Html),
CAExport(Export.Md)]
public class A
{
[CAAnalyze(3.5f)]
[CAAnalyze(13.5f)]
public static float Heavy(float a)
{
var b = Do1(a);
var c = Do1(b);
if (a > 10)
c += Aaa(a);
return c + b;
}
[CAAnalyze(6f)]
public static float Square(float a)
{
return a * a;
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static float Do1(float a)
{
return a * 2;
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static float Aaa(float h)
{
return h * h * h;
}
}
```
[See the output](./Samples/CodegenAnalysis.Benchmarks.Sample/CodegenAnalysis.Artifacts).