Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e420f84
Add Native AOT to CI
vonzshik Jan 22, 2023
15e035c
Fix build path
vonzshik Jan 22, 2023
4626142
Fix pg user password
vonzshik Jan 22, 2023
c1e4713
Fix database
vonzshik Jan 22, 2023
9817b66
Fix database name
vonzshik Jan 22, 2023
771c4f3
CREATE DATABASE can't run in transaction block
vonzshik Jan 22, 2023
be292e9
Report binary size
vonzshik Jan 22, 2023
93ea06d
Remove Console.WriteLine
vonzshik Jan 22, 2023
c2fdeb7
Dump mstat
vonzshik Jan 22, 2023
26afd18
Fix mstatdumper path
vonzshik Jan 22, 2023
a786a18
Fix package version
vonzshik Jan 22, 2023
0d5a7c7
Disable nrt
vonzshik Jan 22, 2023
f70ee98
A bit more space
vonzshik Jan 22, 2023
10bc865
Up the version of sdk
vonzshik Jan 22, 2023
30f4974
Add size assert
vonzshik Jan 22, 2023
6392b8c
Final check
vonzshik Jan 22, 2023
98d3e04
Try to disable globalization
vonzshik Jan 22, 2023
8b44f24
Revert "Try to disable globalization"
vonzshik Jan 22, 2023
d5b5416
Try to remove symbols
vonzshik Jan 22, 2023
3d13367
Revert "Try to remove symbols"
vonzshik Jan 22, 2023
872368d
Try to set PublishTrimmed
vonzshik Jan 22, 2023
69c72df
Remove trimming tests
vonzshik Jan 22, 2023
b2a6793
Try to strip some more
vonzshik Jan 22, 2023
95e28ac
Update size threshold
vonzshik Jan 22, 2023
03e3852
Let's try github summary
vonzshik Jan 22, 2023
c752767
Upgrade summary
vonzshik Jan 22, 2023
1d995a0
Pretty output for blobs
vonzshik Jan 22, 2023
11336ba
Try to add details
vonzshik Jan 22, 2023
14d6368
Also print binary size to summary
vonzshik Jan 22, 2023
bc82b1f
Hide behind details other tables
vonzshik Jan 22, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions .github/workflows/nativeAOT.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
name: NativeAOT

on:
push:
branches:
- main
- 'hotfix/**'
tags:
- '*'
pull_request:

env:
dotnet_sdk_version: '7.0.102'
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true

jobs:
build:
runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04]
pg_major: [15]

steps:
- name: Checkout
uses: actions/checkout@v3

- name: NuGet Cache
uses: actions/cache@v3
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/Directory.Build.targets') }}
restore-keys: |
${{ runner.os }}-nuget-

- name: Setup .NET Core SDK
uses: actions/setup-dotnet@v3.0.3
with:
dotnet-version: |
${{ env.dotnet_sdk_version }}

- name: Setup Native AOT prerequisites
run: sudo apt-get install clang zlib1g-dev
shell: bash

- name: Build
run: dotnet publish test/Npgsql.NativeAotTests/Npgsql.NativeAotTests.csproj -r linux-x64 -c Release -f net7.0
shell: bash

- name: Start PostgreSQL ${{ matrix.pg_major }} (Linux)
if: startsWith(matrix.os, 'ubuntu')
run: |
# First uninstall any PostgreSQL installed on the image
dpkg-query -W --showformat='${Package}\n' 'postgresql-*' | xargs sudo dpkg -P postgresql

# Import the repository signing key
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -

sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ jammy-pgdg main ${{ matrix.pg_major }}" >> /etc/apt/sources.list.d/pgdg.list'
sudo apt-get update -qq
sudo apt-get install -qq postgresql-${{ matrix.pg_major }}
export PGDATA=/etc/postgresql/${{ matrix.pg_major }}/main

sudo -u postgres psql -c "CREATE USER npgsql_tests SUPERUSER PASSWORD 'npgsql_tests'"
sudo -u postgres psql -c "CREATE DATABASE npgsql_tests"

sudo pg_ctlcluster ${{ matrix.pg_major }} main restart

# Uncomment the following to SSH into the agent running the build (https://github.com/mxschmitt/action-tmate)
#- uses: actions/checkout@v3
#- name: Setup tmate session
# uses: mxschmitt/action-tmate@v3

- name: Run
run: test/Npgsql.NativeAotTests/bin/Release/net7.0/linux-x64/native/Npgsql.NativeAotTests

- name: Write binary size to summary
run: |
size="$(ls -l test/Npgsql.NativeAotTests/bin/Release/net7.0/linux-x64/native/Npgsql.NativeAotTests | cut -d ' ' -f 5)"
echo "Binary size is $size bytes ($((size / (1024 * 1024))) mb)" >> $GITHUB_STEP_SUMMARY

- name: Dump mstat
run: dotnet run --project test/MStatDumper/MStatDumper.csproj -c release -- "test/Npgsql.NativeAotTests/obj/Release/net7.0/linux-x64/native/Npgsql.NativeAotTests.mstat" md >> $GITHUB_STEP_SUMMARY

- name: Assert binary size
run: |
size="$(ls -l test/Npgsql.NativeAotTests/bin/Release/net7.0/linux-x64/native/Npgsql.NativeAotTests | cut -d ' ' -f 5)"
echo "Binary size is $size bytes ($((size / (1024 * 1024))) mb)"

if (( size > 36700160 )); then
echo "Binary size exceeds 35mb threshold"
exit 1
fi
3 changes: 3 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,8 @@
<PackageVersion Include="BenchmarkDotNet" Version="0.13.4" />
<PackageVersion Include="Microsoft.Data.SqlClient" Version="5.0.1" />
<PackageVersion Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.4" />

<!-- NativeAOT -->
<PackageVersion Include="Mono.Cecil" Version="0.11.4" />
</ItemGroup>
</Project>
14 changes: 14 additions & 0 deletions test/MStatDumper/MStatDumper.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Mono.Cecil" />
</ItemGroup>

</Project>
235 changes: 235 additions & 0 deletions test/MStatDumper/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
using Mono.Cecil;
using Mono.Cecil.Rocks;

namespace MStatDumper
{
internal class Program
{
static void Main(string[] args)
{
if (args.Length == 0)
{
throw new Exception("Must provide the path to mstat file. It's in {project}/obj/Release/{TFM}/{os}/native/{project}.mstat");
}

var markDownStyleOutput = args.Length > 1 && args[1] == "md";

var asm = AssemblyDefinition.ReadAssembly(args[0]);
var globalType = (TypeDefinition)asm.MainModule.LookupToken(0x02000001);

var types = globalType.Methods.First(x => x.Name == "Types");
var typeStats = GetTypes(types).ToList();
var typeSize = typeStats.Sum(x => x.Size);
var typesByModules = typeStats.GroupBy(x => x.Type.Scope).Select(x => new { x.Key.Name, Sum = x.Sum(x => x.Size) }).ToList();
if (markDownStyleOutput)
{
Console.WriteLine("<details>");
Console.WriteLine($"<summary>Types Total Size {typeSize:n0}</summary>");
Console.WriteLine();
Console.WriteLine("<br>");
Console.WriteLine();
Console.WriteLine("| Name | Size |");
Console.WriteLine("| --- | --- |");
foreach (var m in typesByModules.OrderByDescending(x => x.Sum))
{
Console.WriteLine($"| {m.Name.Replace("`", "\\`")} | {m.Sum:n0} |");
}
Console.WriteLine();
Console.WriteLine("</details>");
}
else
{
Console.WriteLine($"// ********** Types Total Size {typeSize:n0}");
foreach (var m in typesByModules.OrderByDescending(x => x.Sum))
{
Console.WriteLine($"{m.Name,-70} {m.Sum,9:n0}");
}
Console.WriteLine("// **********");
}

Console.WriteLine();

var methods = globalType.Methods.First(x => x.Name == "Methods");
var methodStats = GetMethods(methods).ToList();
var methodSize = methodStats.Sum(x => x.Size + x.GcInfoSize + x.EhInfoSize);
var methodsByModules = methodStats.GroupBy(x => x.Method.DeclaringType.Scope).Select(x => new { x.Key.Name, Sum = x.Sum(x => x.Size + x.GcInfoSize + x.EhInfoSize) }).ToList();
if (markDownStyleOutput)
{
Console.WriteLine("<details>");
Console.WriteLine($"<summary>Methods Total Size {methodSize:n0}</summary>");
Console.WriteLine();
Console.WriteLine("<br>");
Console.WriteLine();
Console.WriteLine("| Name | Size |");
Console.WriteLine("| --- | --- |");
foreach (var m in methodsByModules.OrderByDescending(x => x.Sum))
{
Console.WriteLine($"| {m.Name.Replace("`", "\\`")} | {m.Sum:n0} |");
}
Console.WriteLine();
Console.WriteLine("</details>");
}
else
{
Console.WriteLine($"// ********** Methods Total Size {methodSize:n0}");
foreach (var m in methodsByModules.OrderByDescending(x => x.Sum))
{
Console.WriteLine($"{m.Name,-70} {m.Sum,9:n0}");
}
Console.WriteLine("// **********");
}

Console.WriteLine();

string FindNamespace(TypeReference type)
{
var current = type;
while (true)
{
if (!String.IsNullOrEmpty(current.Namespace))
{
return current.Namespace;
}

if (current.DeclaringType == null)
{
return current.Name;
}

current = current.DeclaringType;
}
}

var methodsByNamespace = methodStats.Select(x => new TypeStats { Type = x.Method.DeclaringType, Size = x.Size + x.GcInfoSize + x.EhInfoSize }).Concat(typeStats).GroupBy(x => FindNamespace(x.Type)).Select(x => new { x.Key, Sum = x.Sum(x => x.Size) }).ToList();
if (markDownStyleOutput)
{
Console.WriteLine("<details>");
Console.WriteLine("<summary>Size By Namespace</summary>");
Console.WriteLine();
Console.WriteLine("<br>");
Console.WriteLine();
Console.WriteLine("| Name | Size |");
Console.WriteLine("| --- | --- |");
foreach (var m in methodsByNamespace.OrderByDescending(x => x.Sum))
{
Console.WriteLine($"| {m.Key.Replace("`", "\\`")} | {m.Sum:n0} |");
}
Console.WriteLine();
Console.WriteLine("</details>");
}
else
{
Console.WriteLine("// ********** Size By Namespace");
foreach (var m in methodsByNamespace.OrderByDescending(x => x.Sum))
{
Console.WriteLine($"{m.Key,-70} {m.Sum,9:n0}");
}
Console.WriteLine("// **********");
}

Console.WriteLine();

var blobs = globalType.Methods.First(x => x.Name == "Blobs");
var blobStats = GetBlobs(blobs).ToList();
var blobSize = blobStats.Sum(x => x.Size);
if (markDownStyleOutput)
{
Console.WriteLine("<details>");
Console.WriteLine($"<summary>Blobs Total Size {blobSize:n0}</summary>");
Console.WriteLine();
Console.WriteLine("<br>");
Console.WriteLine();
Console.WriteLine("| Name | Size |");
Console.WriteLine("| --- | --- |");
foreach (var m in blobStats.OrderByDescending(x => x.Size))
{
Console.WriteLine($"| {m.Name.Replace("`", "\\`")} | {m.Size:n0} |");
}
Console.WriteLine();
Console.WriteLine("</details>");
}
else
{
Console.WriteLine($"// ********** Blobs Total Size {blobSize:n0}");
foreach (var m in blobStats.OrderByDescending(x => x.Size))
{
Console.WriteLine($"{m.Name,-70} {m.Size,9:n0}");
}
Console.WriteLine("// **********");
}
}

public static IEnumerable<TypeStats> GetTypes(MethodDefinition types)
{
types.Body.SimplifyMacros();
var il = types.Body.Instructions;
for (int i = 0; i + 2 < il.Count; i += 2)
{
var type = (TypeReference)il[i + 0].Operand;
var size = (int)il[i + 1].Operand;
yield return new TypeStats
{
Type = type,
Size = size
};
}
}

public static IEnumerable<MethodStats> GetMethods(MethodDefinition methods)
{
methods.Body.SimplifyMacros();
var il = methods.Body.Instructions;
for (int i = 0; i + 4 < il.Count; i += 4)
{
var method = (MethodReference)il[i + 0].Operand;
var size = (int)il[i + 1].Operand;
var gcInfoSize = (int)il[i + 2].Operand;
var ehInfoSize = (int)il[i + 3].Operand;
yield return new MethodStats
{
Method = method,
Size = size,
GcInfoSize = gcInfoSize,
EhInfoSize = ehInfoSize
};
}
}

public static IEnumerable<BlobStats> GetBlobs(MethodDefinition blobs)
{
blobs.Body.SimplifyMacros();
var il = blobs.Body.Instructions;
for (int i = 0; i + 2 < il.Count; i += 2)
{
var name = (string)il[i + 0].Operand;
var size = (int)il[i + 1].Operand;
yield return new BlobStats
{
Name = name,
Size = size
};
}
}
}

public class TypeStats
{
public string MethodName { get; set; }
public TypeReference Type { get; set; }
public int Size { get; set; }
}

public class MethodStats
{
public MethodReference Method { get; set; }
public int Size { get; set; }
public int GcInfoSize { get; set; }
public int EhInfoSize { get; set; }
}

public class BlobStats
{
public string Name { get; set; }
public int Size { get; set; }
}
}
19 changes: 19 additions & 0 deletions test/Npgsql.NativeAotTests/Npgsql.NativeAotTests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>exe</OutputType>
<PublishAot>true</PublishAot>
<TargetFrameworks>net7.0</TargetFrameworks>
<IlcGenerateMstatFile>true</IlcGenerateMstatFile>
<StaticallyLinked>true</StaticallyLinked>
<InvariantGlobalization>true</InvariantGlobalization>
<StaticOpenSslLinking>true</StaticOpenSslLinking>
<StaticExecutable>true</StaticExecutable>
<StripSymbols>true</StripSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../../src/Npgsql/Npgsql.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Remove="GitHubActionsTestLogger" />
</ItemGroup>
</Project>
Loading