CodegenAnalysis.Assertions
0.1.0-alpha-1659621383-f874603
See the version list below for details.
dotnet add package CodegenAnalysis.Assertions --version 0.1.0-alpha-1659621383-f874603
NuGet\Install-Package CodegenAnalysis.Assertions -Version 0.1.0-alpha-1659621383-f874603
<PackageReference Include="CodegenAnalysis.Assertions" Version="0.1.0-alpha-1659621383-f874603" />
paket add CodegenAnalysis.Assertions --version 0.1.0-alpha-1659621383-f874603
#r "nuget: CodegenAnalysis.Assertions, 0.1.0-alpha-1659621383-f874603"
// Install CodegenAnalysis.Assertions as a Cake Addin #addin nuget:?package=CodegenAnalysis.Assertions&version=0.1.0-alpha-1659621383-f874603&prerelease // Install CodegenAnalysis.Assertions as a Cake Tool #tool nuget:?package=CodegenAnalysis.Assertions&version=0.1.0-alpha-1659621383-f874603&prerelease
CodegenAnalysis
⚠️ The library is in progress (alpha versioning).
⚠️ No expected behaviour, no documentation, no backward compatibility.
<img align="right" src="./logo1t.png" width=200>
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.
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
static int AddAndMul(int a, int b) => a + b * a;
...
var ci = CodegenInfo.Obrain(() => AddAndMul(3, 5));
Console.WriteLine(ci);
Output:
00007FFD752E42F0 8BC2 mov eax,edx
00007FFD752E42F2 0FAFC1 imul eax,ecx
00007FFD752E42F5 03C1 add eax,ecx
00007FFD752E42F7 C3 ret
CodegenAnalysis.Assertions
Verifying the size of the codegen
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
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
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
CodegenBenchmarkRunner.Run<A>();
[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;
}
}
Output in markdown (with these Export
attributes you will see html and plain output in CodegenAnalysis.Artifacts
):
Codegen analysis report
2022-08-04 13:49 UTC
Summary
Job | Method | Branches | Calls | CodegenSize | StaticStackAllocations |
---|---|---|---|---|---|
(Tier = Default) | Single Heavy(Single) | 1 | 3 | 107 B | 16 B |
(Tier = Default) | Single Square(Single) | - | - | 34 B | 16 B |
(Tier = Tier1) | Single Heavy(Single) | 1 | 3 | 88 B | 16 B |
(Tier = Tier1) | Single Square(Single) | - | - | 8 B | ? |
Codegens
Single Heavy(Single): Default
00007F2131C20570 55 push rbp
00007F2131C20571 4883EC10 sub rsp,10h
00007F2131C20575 C5F877 vzeroupper
00007F2131C20578 488D6C2410 lea rbp,[rsp+10h]
00007F2131C2057D 33C0 xor eax,eax
00007F2131C2057F 8945F8 mov [rbp-8],eax
00007F2131C20582 8945F4 mov [rbp-0Ch],eax
00007F2131C20585 C5FA1145FC vmovss [rbp-4],xmm0
00007F2131C2058A C5FA1045FC vmovss xmm0,[rbp-4]
00007F2131C2058F E8341FB4FF call Single Do1(Single) (00007F21317624C8)
00007F2131C20594 C5FA1145F8 vmovss [rbp-8],xmm0
00007F2131C20599 C5FA1045F8 vmovss xmm0,[rbp-8]
00007F2131C2059E E8251FB4FF call Single Do1(Single) (00007F21317624C8)
00007F2131C205A3 C5FA1145F4 vmovss [rbp-0Ch],xmm0
00007F2131C205A8 C5FA1045FC vmovss xmm0,[rbp-4]
00007F2131C205AD C5F82E0533000000 vucomiss xmm0,[rel 7F21`31C2`05E8h]
┌─00007F2131C205B5 7614 jbe short 0000`7F21`31C2`05CBh
│ 00007F2131C205B7 C5FA1045FC vmovss xmm0,[rbp-4]
│ 00007F2131C205BC E80F1FB4FF call 0000`7F21`3176`24D0h
│ 00007F2131C205C1 C5FA5845F4 vaddss xmm0,xmm0,[rbp-0Ch]
│ 00007F2131C205C6 C5FA1145F4 vmovss [rbp-0Ch],xmm0
└>00007F2131C205CB C5FA1045F4 vmovss xmm0,[rbp-0Ch]
00007F2131C205D0 C5FA5845F8 vaddss xmm0,xmm0,[rbp-8]
00007F2131C205D5 4883C410 add rsp,10h
00007F2131C205D9 5D pop rbp
00007F2131C205DA C3 ret
Single Heavy(Single): Tier1
00007F2131C3E290 55 push rbp
00007F2131C3E291 4883EC10 sub rsp,10h
00007F2131C3E295 C5F877 vzeroupper
00007F2131C3E298 488D6C2410 lea rbp,[rsp+10h]
00007F2131C3E29D C5FA1145FC vmovss [rbp-4],xmm0
00007F2131C3E2A2 E82142B2FF call Single Do1(Single) (00007F21317624C8)
00007F2131C3E2A7 C5FA1145F8 vmovss [rbp-8],xmm0
00007F2131C3E2AC E81742B2FF call Single Do1(Single) (00007F21317624C8)
00007F2131C3E2B1 C5FA1145F4 vmovss [rbp-0Ch],xmm0
00007F2131C3E2B6 C5FA104DFC vmovss xmm1,[rbp-4]
00007F2131C3E2BB C5F82E0D35000000 vucomiss xmm1,[rel 7F21`31C3`E2F8h]
┌─00007F2131C3E2C3 7613 jbe short 0000`7F21`31C3`E2D8h
│ 00007F2131C3E2C5 C5F828C1 vmovaps xmm0,xmm1
│ 00007F2131C3E2C9 E80242B2FF call 0000`7F21`3176`24D0h
│ 00007F2131C3E2CE C5FA5845F4 vaddss xmm0,xmm0,[rbp-0Ch]
│ 00007F2131C3E2D3 C5FA1145F4 vmovss [rbp-0Ch],xmm0
└>00007F2131C3E2D8 C5FA1045F4 vmovss xmm0,[rbp-0Ch]
00007F2131C3E2DD C5FA5845F8 vaddss xmm0,xmm0,[rbp-8]
00007F2131C3E2E2 4883C410 add rsp,10h
00007F2131C3E2E6 5D pop rbp
00007F2131C3E2E7 C3 ret
Single Square(Single): Default
00007F2131C3C2F0 55 push rbp
00007F2131C3C2F1 4883EC10 sub rsp,10h
00007F2131C3C2F5 C5F877 vzeroupper
00007F2131C3C2F8 488D6C2410 lea rbp,[rsp+10h]
00007F2131C3C2FD C5FA1145FC vmovss [rbp-4],xmm0
00007F2131C3C302 C5FA1045FC vmovss xmm0,[rbp-4]
00007F2131C3C307 C5FA5945FC vmulss xmm0,xmm0,[rbp-4]
00007F2131C3C30C 4883C410 add rsp,10h
00007F2131C3C310 5D pop rbp
00007F2131C3C311 C3 ret
Single Square(Single): Tier1
00007F2131C475A0 C5F877 vzeroupper
00007F2131C475A3 C5FA59C0 vmulss xmm0,xmm0,xmm0
00007F2131C475A7 C3 ret
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 is compatible. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- CodegenAnalysis (>= 0.1.0-alpha-1659621383-f874603)
-
.NETStandard 2.1
- CodegenAnalysis (>= 0.1.0-alpha-1659621383-f874603)
-
net5.0
- CodegenAnalysis (>= 0.1.0-alpha-1659621383-f874603)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
1.0.0 | 883 | 8/14/2022 |
0.2.0-alpha | 570 | 8/10/2022 |
0.1.0-alpha-1659621383-f874603 | 588 | 8/4/2022 |
0.1.0-alpha-1639660460-222ddd2 | 643 | 12/16/2021 |
0.1.0-alpha-1639290344-32dff2a | 591 | 12/12/2021 |
0.0.10-alpha | 637 | 12/10/2021 |
0.0.9-alpha | 599 | 12/7/2021 |
0.0.8-alpha | 615 | 12/5/2021 |
0.0.7-alpha | 627 | 11/30/2021 |
0.0.6-alpha | 631 | 11/28/2021 |
0.0.5-alpha | 602 | 11/27/2021 |
0.0.4-alpha | 647 | 11/27/2021 |
0.0.3-alpha | 2,940 | 11/25/2021 |
0.0.0-alpha-1639289799-a37ffcf | 613 | 12/12/2021 |
Forward jumps visualization and bugs fixed.