Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
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: 10 days 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 (about 3 years ago)
- Default Branch: main
- Last Pushed: 2022-12-04T19:29:10.000Z (almost 2 years ago)
- Last Synced: 2024-11-01T13:41:59.512Z (17 days ago)
- Topics: codegen, dotnet, jit, performance, performance-analysis
- Language: C#
- Homepage:
- Size: 252 KB
- Stars: 22
- Watchers: 4
- Forks: 0
- Open Issues: 8
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# CodegenAnalysis
![](https://img.shields.io/static/v1?label=Lowest+target&message=netstandard2.0&color=purple&logo=dotnet)
![](https://img.shields.io/static/v1?label=Windows&message=Supported&color=brightgreen&logo=windows)
![](https://img.shields.io/static/v1?label=Linux&message=Supported&color=brightgreen&logo=linux)
![](https://img.shields.io/static/v1?label=MacOS&message=Supported&color=brightgreen&logo=apple)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
[![Nuget (with prereleases)](https://img.shields.io/nuget/vpre/CodegenAnalysis?label=NuGet&logo=nuget)](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
[![Nuget (with prereleases)](https://img.shields.io/nuget/vpre/CodegenAnalysis.Assertions?label=NuGet&logo=nuget)](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
[![Nuget (with prereleases)](https://img.shields.io/nuget/vpre/CodegenAnalysis.Benchmarks?label=NuGet&logo=nuget)](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).