Skip to content

[assembly-preparer] Speed up InlineDlfcnMethodsStep.#26039

Draft
rolfbjarne wants to merge 1 commit into
mainfrom
dev/rolf/assembly-preparer-inline-dlfcn-perf
Draft

[assembly-preparer] Speed up InlineDlfcnMethodsStep.#26039
rolfbjarne wants to merge 1 commit into
mainfrom
dev/rolf/assembly-preparer-inline-dlfcn-perf

Conversation

@rolfbjarne

Copy link
Copy Markdown
Member

InlineDlfcnMethodsStep iterated every type and every method (and every
instruction of every method with a body) in every assembly, looking for calls to
ObjCRuntime.Dlfcn to inline. Two changes make this cheaper:

  • Skip whole assemblies that can't contain Dlfcn calls. Dlfcn lives in the
    product assembly, so an assembly that neither is nor references the product
    assembly (the BCL, most third-party code) can't call it. Check that (cheapest
    first: the assembly references, then whether it's the product assembly, then
    finally whether it references the Dlfcn type) once per assembly and skip the
    whole thing - types, methods and instructions - otherwise.

  • Check the declaring type's simulator availability once per type in ProcessType
    instead of once per method. It only depends on the type, so recomputing it for
    every method (each call scans the type's availability attributes) was wasteful.

For monotouch-test's assemblies (MySimpleApp, ios simulator) this cut the time
spent in InlineDlfcnMethodsStep roughly in half for link None (2.85s -> 1.65s,
dominated by the un-skippable product assembly) and ~6x for SdkOnly (1.58s ->
0.27s).

Verified with monotouch-test on iOS (0 failed) with the inline-dlfcn-methods-strict
and inline-dlfcn-methods-compat variations (which exercise the actual inlining)
as well as release|linksdk.

Build performance on iOS (MonoVM):

Project Runtime identifier Link mode PrepareAssemblies=false PrepareAssemblies=true Difference
monotouch-test ios-arm64 None 00:02:19.76 00:02:13.53 -00:00:06.23
monotouch-test ios-arm64 SdkOnly 00:01:26.94 00:01:47.17 00:00:20.22
monotouch-test iossimulator-arm64 None 00:01:45.58 00:01:43.90 -00:00:01.68
monotouch-test iossimulator-arm64 SdkOnly 00:01:18.42 00:01:23.84 00:00:05.42
MySimpleApp ios-arm64 None 00:01:14.39 00:01:16.94 00:00:02.54
MySimpleApp ios-arm64 SdkOnly 00:00:22.02 00:00:45.90 00:00:23.87
MySimpleApp iossimulator-arm64 None 00:00:53.94 00:00:54.32 00:00:00.37
MySimpleApp iossimulator-arm64 SdkOnly 00:00:19.17 00:00:25.65 00:00:06.47

Build performance on macOS (CoreCLR):

Project Runtime identifier Link mode PrepareAssemblies=false PrepareAssemblies=true Difference
monotouch-test osx-arm64 None 00:00:56.09 00:00:51.21 -00:00:04.87
monotouch-test osx-arm64 SdkOnly 00:00:53.56 00:00:52.37 -00:00:01.18
MySimpleApp osx-arm64 None 00:00:09.83 00:00:09.50 -00:00:00.33
MySimpleApp osx-arm64 SdkOnly 00:00:09.44 00:00:08.84 -00:00:00.60

InlineDlfcnMethodsStep iterated every type and every method (and every
instruction of every method with a body) in every assembly, looking for calls to
ObjCRuntime.Dlfcn to inline. Two changes make this cheaper:

* Skip whole assemblies that can't contain Dlfcn calls. Dlfcn lives in the
  product assembly, so an assembly that neither is nor references the product
  assembly (the BCL, most third-party code) can't call it. Check that (cheapest
  first: the assembly references, then whether it's the product assembly, then
  finally whether it references the Dlfcn type) once per assembly and skip the
  whole thing - types, methods and instructions - otherwise.

* Check the declaring type's simulator availability once per type in ProcessType
  instead of once per method. It only depends on the type, so recomputing it for
  every method (each call scans the type's availability attributes) was wasteful.

For monotouch-test's assemblies (MySimpleApp, ios simulator) this cut the time
spent in InlineDlfcnMethodsStep roughly in half for link None (2.85s -> 1.65s,
dominated by the un-skippable product assembly) and ~6x for SdkOnly (1.58s ->
0.27s).

Verified with monotouch-test on iOS (0 failed) with the inline-dlfcn-methods-strict
and inline-dlfcn-methods-compat variations (which exercise the actual inlining)
as well as release|linksdk.

Build performance on iOS (MonoVM):

| Project        | Runtime identifier | Link mode | PrepareAssemblies=false | PrepareAssemblies=true | Difference   |
| -------------- | ------------------ | --------- | ----------------------- | ---------------------- | ------------ |
| monotouch-test | ios-arm64          | None      |  00:02:19.76            |  00:02:13.53           | -00:00:06.23 |
| monotouch-test | ios-arm64          | SdkOnly   |  00:01:26.94            |  00:01:47.17           |  00:00:20.22 |
| monotouch-test | iossimulator-arm64 | None      |  00:01:45.58            |  00:01:43.90           | -00:00:01.68 |
| monotouch-test | iossimulator-arm64 | SdkOnly   |  00:01:18.42            |  00:01:23.84           |  00:00:05.42 |
| MySimpleApp    | ios-arm64          | None      |  00:01:14.39            |  00:01:16.94           |  00:00:02.54 |
| MySimpleApp    | ios-arm64          | SdkOnly   |  00:00:22.02            |  00:00:45.90           |  00:00:23.87 |
| MySimpleApp    | iossimulator-arm64 | None      |  00:00:53.94            |  00:00:54.32           |  00:00:00.37 |
| MySimpleApp    | iossimulator-arm64 | SdkOnly   |  00:00:19.17            |  00:00:25.65           |  00:00:06.47 |

Build performance on macOS (CoreCLR):

| Project        | Runtime identifier | Link mode | PrepareAssemblies=false | PrepareAssemblies=true | Difference   |
| -------------- | ------------------ | --------- | ----------------------- | ---------------------- | ------------ |
| monotouch-test | osx-arm64          | None      |  00:00:56.09            |  00:00:51.21           | -00:00:04.87 |
| monotouch-test | osx-arm64          | SdkOnly   |  00:00:53.56            |  00:00:52.37           | -00:00:01.18 |
| MySimpleApp    | osx-arm64          | None      |  00:00:09.83            |  00:00:09.50           | -00:00:00.33 |
| MySimpleApp    | osx-arm64          | SdkOnly   |  00:00:09.44            |  00:00:08.84           | -00:00:00.60 |

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Optimizes the assembly-preparer linker step InlineDlfcnMethodsStep to reduce unnecessary scanning work when inlining ObjCRuntime.Dlfcn calls, improving overall link/prepare performance. Also updates performance tests to cover the intended runtime split (MonoVM on iOS, CoreCLR on macOS).

Changes:

  • Skip processing entire assemblies that cannot contain ObjCRuntime.Dlfcn calls by checking product-assembly relationship and type references once per assembly.
  • Cache simulator-availability checks at the type level (once per type) instead of repeating them for every method.
  • Split the PrepareAssemblies performance test into separate MonoVM and CoreCLR test entry points.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
tools/dotnet-linker/Steps/InlineDlfcnMethodsStep.cs Avoids type/method/IL iteration for assemblies that cannot reference ObjCRuntime.Dlfcn, and reduces repeated simulator-availability checks.
tests/dotnet/UnitTests/PerformanceTests.cs Splits performance coverage into MonoVM (iOS) and CoreCLR (macOS) test cases while reusing shared logic.

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ API diff for current PR / commit

NET (empty diffs)

✅ API diff vs stable

NET (empty diffs)

ℹ️ Generator diff

Generator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes)

Pipeline on Agent
Hash: bf45f88d942c8c351c67b7e50ae499faed681858 [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

🚀 [CI Build #bf45f88] Test results 🚀

Test results

✅ All tests passed on VSTS: test results.

🎉 All 199 tests passed 🎉

Tests counts

✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download
✅ cecil: All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (iOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (MacCatalyst): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (macOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (Multiple platforms): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (tvOS): All 1 tests passed. Html Report (VSDrops) Download
✅ framework: All 2 tests passed. Html Report (VSDrops) Download
✅ fsharp: All 4 tests passed. Html Report (VSDrops) Download
✅ generator: All 5 tests passed. Html Report (VSDrops) Download
✅ interdependent-binding-projects: All 4 tests passed. Html Report (VSDrops) Download
✅ introspection: All 4 tests passed. Html Report (VSDrops) Download
✅ linker (iOS): All 15 tests passed. Html Report (VSDrops) Download
✅ linker (MacCatalyst): All 15 tests passed. Html Report (VSDrops) Download
✅ linker (macOS): All 21 tests passed. Html Report (VSDrops) Download
✅ linker (tvOS): All 15 tests passed. Html Report (VSDrops) Download
✅ monotouch (iOS): All 18 tests passed. Html Report (VSDrops) Download
✅ monotouch (MacCatalyst): All 17 tests passed. Html Report (VSDrops) Download
✅ monotouch (macOS): All 18 tests passed. Html Report (VSDrops) Download
✅ monotouch (tvOS): All 18 tests passed. Html Report (VSDrops) Download
✅ msbuild: All 2 tests passed. Html Report (VSDrops) Download
✅ sharpie: All 1 tests passed. Html Report (VSDrops) Download
✅ windows: All 3 tests passed. Html Report (VSDrops) Download
✅ xcframework: All 4 tests passed. Html Report (VSDrops) Download
✅ xtro: All 1 tests passed. Html Report (VSDrops) Download

macOS tests

✅ Tests on macOS Monterey (12): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Ventura (13): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sonoma (14): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sequoia (15): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Tahoe (26): All 5 tests passed. Html Report (VSDrops) Download

Linux Build Verification

Linux build succeeded

Pipeline on Agent
Hash: bf45f88d942c8c351c67b7e50ae499faed681858 [PR build]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants