Skip to content

Conversation

@radekdoulik
Copy link
Member

@radekdoulik radekdoulik commented Dec 18, 2025

And remove obsolete code around .ni assemblies and executables

Copilot AI review requested due to automatic review settings December 18, 2025 14:41
@radekdoulik radekdoulik marked this pull request as draft December 18, 2025 14:42
@radekdoulik radekdoulik added this to the Future milestone Dec 18, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR optimizes assembly loading for WebAssembly by removing native image (.ni.dll) probing, which is no longer supported on WASM and can negatively impact startup performance. The change affects only the CoreCLR binder's assembly probing logic.

Key Changes

  • Conditionally excludes .ni.dll from assembly probe candidates when targeting WASM
  • Updates loop iteration to use ARRAY_SIZE macro instead of hardcoded value for better maintainability

@radekdoulik
Copy link
Member Author

radekdoulik commented Dec 18, 2025

@jkotas there's still many places related to .ni.dll.

> git grep ni.dll | wc -l  
      45

Would it be worth to remove .ni.dll support in the whole repo?

@vitek-karas
Copy link
Member

@grendello was looking into something similar for Android (we don't need/want it there either)... and I assume we would like that for iOS as well.
I know that there was a discussion if we should just remove this functionality from the runtime everywhere (personally I've never seen an app which would use this).

@jkotas
Copy link
Member

jkotas commented Dec 18, 2025

Would it be worth to remove .ni.dll support in the whole repo?

Yes, I went over the grep output and it looks all dead code, outdated comments, or local workaround for compat (PdbWriter.cs, CallChainProfile.cs, DumpModel.cs - these should be kept). Can you give it a shot to clean up the rest?

@jkotas
Copy link
Member

jkotas commented Dec 22, 2025

Could you please also delete --out-near-input option for crossgen?

@radekdoulik
Copy link
Member Author

There is still a lookup map in https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/ceeload.h#L1667-L1675 which we can possibly get rid of.

I also kept the related parts of tools/aot/crossgen2/Program.cs as it was also in tools/aot area as the other .cs files. Let me know in case this is also obsolete.

@jkotas
Copy link
Member

jkotas commented Dec 22, 2025

There is still a lookup map in https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/ceeload.h#L1667-L1675 which we can possibly get rid of.

That is just a comment talking about .ni.dll. The map itself is no specific to .ni.dlls. You can fix the comment so that it is not talking about .ni.dll. "When that happens a.ni.dll stores" -> "When that happens a.dll R2R image stores"

@radekdoulik
Copy link
Member Author

Could you please also delete --out-near-input option for crossgen?

What about the single file compilation, should I remove it too or keep it and not complain about --out-near-input option?

@jkotas
Copy link
Member

jkotas commented Dec 22, 2025

What about the single file compilation, should I remove it too or keep it and not complain about --out-near-input option?

I do not see --out-near-input and --single-file-compilation used or tested anywhere. All of it looks like dead code to me.

@elinor-fung @davidwrighton Could you please confirm that it is fine to delete this?

@am11
Copy link
Member

am11 commented Dec 24, 2025

We can also delete .ni.dll from bringup script (used by new platform ports):

--- a/src/tests/Common/scripts/bringup_runtest.sh
+++ b/src/tests/Common/scripts/bringup_runtest.sh
@@ -424,14 +424,6 @@ function create_core_overlay {
     fi
     cp -f -v "$testDependenciesDir/"xunit* "$coreOverlayDir/" 2>/dev/null
     cp -n -v "$testDependenciesDir/"* "$coreOverlayDir/" 2>/dev/null
-    if [ -f "$coreOverlayDir/mscorlib.ni.dll" ]; then
-        # Test dependencies come from a Windows build, and mscorlib.ni.dll would be the one from Windows
-        rm -f "$coreOverlayDir/mscorlib.ni.dll"
-    fi
-    if [ -f "$coreOverlayDir/System.Private.CoreLib.ni.dll" ]; then
-        # Test dependencies come from a Windows build, and System.Private.CoreLib.ni.dll would be the one from Windows
-        rm -f "$coreOverlayDir/System.Private.CoreLib.ni.dll"
-    fi
     copy_test_native_bin_to_test_root $coreOverlayDir
 }
 
@@ -452,7 +444,7 @@ function precompile_overlay_assemblies {
     if [[ "$doCrossgen" == 1 ]]; then
         local overlayDir=$CORE_ROOT
 
-        filesToPrecompile=$(find -L $overlayDir -iname \*.dll -not -iname \*.ni.dll -not -iname \*-ms-win-\* -type f )
+        filesToPrecompile=$(find -L $overlayDir -iname \*.dll -not -iname \*-ms-win-\* -type f )
         for fileToPrecompile in ${filesToPrecompile}
         do
             local filename=${fileToPrecompile}

These are also not needed?

docs/design/features/jump-stubs.md:scenario. Mscorlib.ni.dll itself has 72 entries in the helper table.
docs/design/features/jump-stubs.md:System.XML.ni.dll has 51 entries, which would lead to 288 and 204 bytes
docs/workflow/editing-and-debugging.md:     * `crossgen` - This is the host program that runs the JIT compiler and produces .NET Native images (`*.ni.dll`)
src/installer/tests/HostActivation.Tests/DependencyResolution/ResolveComponentDependencies.cs:                        .WithAsset("ComponentDependency.ni.dll"))));
src/installer/tests/HostActivation.Tests/DependencyResolution/ResolveComponentDependencies.cs:                .And.HaveStdOutContaining("path: 'ComponentDependency.ni.dll'")
src/libraries/Microsoft.Extensions.DependencyModel/tests/DependencyContextTests.cs:        [InlineData("System.Collections.ni.dll", "System.Collections")]
src/tests/GC/Regressions/v2.0-beta2/445488/445488.cs:*** WARNING: Unable to verify checksum for D:\WINDOWS\Microsoft.NET\Framework\v2.0.x86dbg\assembly\NativeImages_v2.0.x86dbg_32\mscorlib\ab6a82069375373ebc7e85bf2de124cb\mscorlib.ni.dll
src/tests/GC/Regressions/v2.0-beta2/445488/445488.cs:*** ERROR: Module load completed but symbols could not be loaded for D:\WINDOWS\Microsoft.NET\Framework\v2.0.x86dbg\assembly\NativeImages_v2.0.x86dbg_32\mscorlib\ab6a82069375373ebc7e85bf2de124cb\mscorlib.ni.dll
src/tests/GC/Regressions/v2.0-beta2/445488/445488.cs:*** WARNING: Unable to verify checksum for D:\WINDOWS\Microsoft.NET\Framework\v2.0.x86dbg\assembly\NativeImages_v2.0.x86dbg_32\System\08fb29f559b89437a7fc3f4a7dbde9c1\System.ni.dll
src/tests/GC/Regressions/v2.0-beta2/445488/445488.cs:*** ERROR: Module load completed but symbols could not be loaded for D:\WINDOWS\Microsoft.NET\Framework\v2.0.x86dbg\assembly\NativeImages_v2.0.x86dbg_32\System\08fb29f559b89437a7fc3f4a7dbde9c1\System.ni.dll
src/tests/JIT/Performance/CodeQuality/Roslyn/CscBench.cs:        // Some CoreCLR packages have System.Private.CoreLib.ni.dll only
src/tests/JIT/Performance/CodeQuality/Roslyn/CscBench.cs:        string nicorlib = Path.Combine(CoreRoot, "System.Private.CoreLib.ni.dll");

@jkoritzinsky
Copy link
Member

I believe --out-near-input and --single-file-compilation were both options in use by @dotnet/samsung.

@tomeksowi
Copy link
Member

I believe --out-near-input and --single-file-compilation were both options in use by @dotnet/samsung.

I don't recall using them for RISC-V

@gbalykov
Copy link
Member

I believe --out-near-input and --single-file-compilation were both options in use by @dotnet/samsung.

Yes, we use these on Tizen to improve crossgen2 performance

@jkotas
Copy link
Member

jkotas commented Dec 26, 2025

Yes, we use these on Tizen to improve crossgen2 performance

Do you still need that now that crossgen2 is compiled with native aot? I assume that this was introduced to workaround startup cost of the managed rewrite of crossgen2.

Also, do you depend on the .ni probing that is being deleted in the rest of the PR? We want to delete that since it is adding unnecessary overhead.

@gbalykov
Copy link
Member

gbalykov commented Jan 3, 2026

Do you still need that now that crossgen2 is compiled with native aot? I assume that this was introduced to workaround startup cost of the managed rewrite of crossgen2.

Yes, this is needed to perform crossgen2 initialization only once instead of for each individual dll compilation (#51154 (comment)). We do not use nativeaot on tizen yet, so it's better to keep these. Looks like "single-file-compilation" and "out-near-input" options can be kept mostly unchanged, creating same *.ni.dll as now (or any other file extension), and an extra step will be needed from users of these options to move *.ni.dll to corresponding *.dll (this step will not be part of crossgen2 itself).

Also, do you depend on the .ni probing that is being deleted in the rest of the PR? We want to delete that since it is adding unnecessary overhead.

Having both plain dll and R2R with the same file extension makes harder to distinguish them: instead of checking file extension we'll need to parse PE. And, similarly, both plain dll and R2R can't be kept in the same path if ni.dll is removed. In overall, this removal probably is not too critical, since we updated part of logic during removal of app .ni probing previously (APP_NI_PATHS), and this also will affect only .NET 11 and above.

@jkotas
Copy link
Member

jkotas commented Jan 3, 2026

@radekdoulik Let's revert the crossgen2 changes for now

Co-authored-by: Jan Kotas <[email protected]>
@radekdoulik radekdoulik marked this pull request as ready for review January 6, 2026 18:41
@radekdoulik radekdoulik enabled auto-merge (squash) January 6, 2026 18:41
@radekdoulik radekdoulik merged commit ef5b188 into dotnet:main Jan 8, 2026
160 of 165 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants