-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unity Support + Mono #36
Comments
Thanks for your interest. I'm not very familiar with the Unity ecosystem at this time so any patches would be welcome. Invoking DistIL.Cli directly would be fine, and it's what the MSBuild task currently does. This is a bit wasteful since it has to reload and process everything from scratch every time, so it might become a problem if it needs to happen very frequently. I should mention that I'm also not very sure how well DistIL output will play with Mono at its current state, because it hardcodes some assumptions about .NET core being the only/main target, so more work might be needed than just the build pipeline. (for example, the IR type system has some reliance on System.Private.CoreLib, and some opts emit direct access to private List/Span fields.) Most of the optimizations you have listed don't seem super complicated to implement at first (the devil is always in the details ofc), apart mostly from interprocedural rewrites. I feel like it would be more productive to fix some of them directly instead of implementing opt passes, but that's not a strong opinion and I understand this might involve some bureaucracy and things move slowly lol. Some minor implementation notes I can think of:
|
Mono's BCL is roughly a 30%/30%/40% split between .NET Framework, .NET Core and custom.
Yeah, ideally stuff like that would just be fixed within Unity itself. That said, many projects are stuck on specific versions of the engine with no feasible upgrade path, so they wouldn't be able to benefit from it.
Mono has intrinsic recognition for the I should also note: Mono (specifically talking about legacy Mono & Unity, rather than the newer Mono from dotnet/runtime) does not recognize [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] Which will give you the same behavior as if you had |
First off, awesome project! I am happy to look into contributing parts of this feature if necessary.
Due to the fact that Unity does not use MSBuild or support NuGet, it is currently non-trivial to consume DistIL from it. Some Unity-specific code would need to be written that uses CompilationPipeline.assemblyCompilationFinished to run DistIL. As Unity only supports .NET Standard 2.1 at the latest, it would likely need to use DistIL.Cli rather than running it in-process.
The JIT codegen in legacy Mono (and by extension, Unity) is typically rather poor, but can be significantly improved with the right tricks. I see a lot of potential in this project for improving the situation.
Some potential optimization passes that come to mind are:
System.Numerics.Vector4
receives hardware acceleration in Mono (System.Numerics.Plane
andSystem.Numerics.Quaternion
do too, if we're talking aboutdotnet/runtime
Mono) so an optimization pass that replacesUnityEngine.Vector4
/Unity.Mathematics.float4
withSystem.Numerics.Vector4
when possible can provide significant improvements.Vector2
/Vector3
/Vector4
/etc. types with theSystem.Numerics
equivalents can significantly improve codegen due to them being intrinsified in the JIT.Vector<T>
is not currently accelerated in Unity due to a bug. A fix exists but it has yet to make its way into an update.System.Numerics.Vector4
due to its intrinsification, passing numerics types (and their third-party equivalents) by reference may often result in better code under Mono.UnityEngine.Quaternion.Inverse
, which just negates thex
,y
andz
components. These could be transformed into regular IL implementations to benefit from inlining and avoid the icall overhead.UnityEngine.GameObject.get_transform
). An optimization pass could inject a new field into types and cache the result of the internal call to avoid the overhead. This could arguably be considered an invalid optimization due to it changing type layouts.System.Runtime.CompilerServices.Unsafe
, but due to the fact that they are not intrinsified by Mono they may not always be inlined and can produce worse code. This is not ideal as theUnsafe
class is not available in-box due to Unity targeting .NET Standard 2.1 and lacking any NuGet support.NativeArray<T>
type that is essentially a pointer and length with some allocation and permissions tracking. Many of its members produce less than ideal code under JIT and due to its indexer being by-value rather than by-ref, it can result in a lot of copying. Burst (Unity's toolchain that runs a subset of IL through LLVM) will often optimize these copies out, among other things. An IL optimization pass can bring regular JIT-mode code a bit closer to its performance.MemoryExtensions.IndexOf
and related APIs that take aStringComparison
currently allocate astring
copy of the input and forward to thestring
-based variants. This results in a significant memory and runtime performance issue. It can be somewhat mitigated by checking forStringComparison.Ordinal
and forwarding to the other overloads that do not take aStringComparison
, but the issue naturally persists for the other comparison types. An IL post processing pass could either embed aSpan
-based implementation of these comparisons, or call into the private Mono BCL methods that perform them (if I recall correctly, they take pointers at the lowest level).The text was updated successfully, but these errors were encountered: