Live data from Hacker News

Unity's Mono problem: C# code runs slower than it should

marekfiser.com

181–190 of 190 posts

Re: Unity's Mono problem: C# code runs slower than it should

#181

Earlier quoted context omitted.

What I agree on is that if we had modern .NET available we'd get a free 2-3x improvement, it would definitely be great. BUT having said that, if you're into performance but unwilling to use the tools available then that's on you. From the article it seems that you're using some form of threading to create things, but you don't really specify which and/or how. The default C# implementations are usually quite poor perf…

Sure, we could use Burst to speed up some strategic parts, but that would not help with the core of the game. To give some context, things are very complex in our game, we have fully dynamic terrain with terrain physics (land-slides), advanced path-finding of hundreds of vehicles (each entity has its own width and height clearance), trains, conveyors and pipes carrying tens or even hundreds of thousands of individual…

>Sure, we could use Burst to speed up some strategic parts... the game would possibly not even exist at that point.

Yeah, the thing with Burst is that its a lot easier to work with if you start with it than having to replace/upgrade code later, especially if you're not familiar with it. A big issue is usually that you create structs with data and they're referencing other structs etc., all those need to be untangled to really make use of Burst. I myself am also a big C# fan, it is a lot easier than using C. Unity has a lot of issues but there's a reason its so widely adopted and used. (I myself am currently working on a Unity C# tool that I believe will speed up code development significantly).

Your game does sound as if its a VERY ripe target for Burst usage based on the elements that you describe, but the real question should be if you need it. For example if you're already running at 60 fps on whatever your mid target hardware is at whatever max + N% load/size for a game instance then you don't need it. But if you're only hitting 40fps and design-wise want to increase e.g. your map size by 2x then it might be something to look into. Also if you look at e.g. Factorio, they spend a LOT of time optimizing systems, but of course you first need to launch the game (which is and should be the priority).

If you have for example 25 systems (e.g. pathfinding, trains, pipes, etc.) and they're evenly balanced then as you say then you won't increase your game speed by 2x by just converting one of those. BUT if for example your pipes are being processed in 4ms per frame, so you instead adopt other strategies like only processing them every Nth frame or doing M pipes per frame; at that point using Burst to just get that 4ms down to 0.5ms might be a really worthwhile target to make your game play better. The same goes for all your systems where the upgrade will have a cumulative effect.

I highly suggest learning just the basics of Burst in your spare time and trying it out on something basic to get the feel of it. As with all code/libraries it'll unfortunately take some time to figure out how to effectively use it. Roughly speaking: - You don't have to have SOA data, but it helps. At the start just convert methods over 1 to 1. - You have to convert most C# container types to Burst ones, for example in struct Vehicle { Wheel[] wheels } you need to change Wheel[] over to NativeArray, and the Wheel struct itself also need to not use complex types etc. Other types such as NativeSpan are also very useful, instead of storing the wheels just use a ref Span to them instead. - After you have basics going you can try out SOA along with more math/less logic so that the code can be vectorized, once you see that big speedup for certain types of code it's hard to go back.

>Could you share some details about your custom thread pool that got 3x speedup? What was the speedup from? It is highly unlikely that a custom thread pool would have any significant impact on the benchmark in our case. As you can see from Figure 3, threaded tasks run for about 25% of the total time and even with Mono, all tasks are reasonably well balanced between threads. Threads utilization is surely over 90% (there is always slight inefficiency towards the end as threads are finishing up, but that's 100's of ms). An "oracle" thread pool could speed tings up by 10% of 25%, so that is not it.

My thread pool itself is pretty standard, it spins up some heavy threads and uses ManualResetEvent to trigger them. Its advantage lies in pre-registering simple Action (with/without parameters) calls to set methods that'll be called when the thread runs; and with more gaming related options for whether we're waiting on thread completion, interleaving them with other threads etc. A big plus is that it has a self-optimization function, so it'll self-adjust the thread count vs the total time runs take, the total # of amounts of items being processed for the given workload etc. so as to automatically find very good sizes for all those elements to use for the target computer, vs just assuming e.g. 32, 64 or 128 inner elements and launching the max available threads on the PC (as thread pools usually do).

>Vectorization could help too but majority of the code is not easily vectorizable. It's all kinds of workloads, loading data, deserialization, initialization of entities, map generation, precomputation of various things. I highly doubt that automatic vectorization from code generated by IL2CPP would bring more than 20% speedup here. The speedup from burst would mostly come from elimination of inefficient code generated by Mono's JIT, not from vectorization.

Yeah, if its startup/generating code that's mostly bypassed by loading a game then its not worth switching over. Do note that code compiled by Burst will in general be more optimized than Mono just due to better tooling, but in general its not worth moving over just for that due to the amount of work you need to do so. The real wins come in if some generating element that's done often is taking too long, or during gameplay where you can replace elements in the game that take e.g. N milliseconds to calculate every frame and drop those down to 1/10th - 1/100th of the time it used to take.

Good luck!

Re: Unity's Mono problem: C# code runs slower than it should

#182

Earlier quoted context omitted.

I'd caveat this slightly as "it depends" For mathy stuff, 100% c# is going to be better. But if you need to round trip to the engine a lot getting stuff in and out of the dotnet heap can actually hurt performance. You also have to be _really_ careful because there are a lot of cases you generate accidental garbage (biggest one is when you use strings that are getting implicitly converted to StringNames every time you…

Yes, it tooks me 2 years to see how much garbage strings conversion to String Names generates and how a fool I was calling something like Input.IsActionPressed("move_right") every frame (sadly it's the example given in the input documentation).

Yup. I remember running dotmemory on a whim and being confused by all the stringnames until I noticed what was in them. They really should put that in the docs to just make a const stringname somewhere. I use a global static class for anything I want in multiple files. But I also tend to just use statics instead of autoloads if I'm doing everything in c#.

Re: Unity's Mono problem: C# code runs slower than it should

#183

Earlier quoted context omitted.

> My dream would be that I can adb into my phone, install the .Net SDK or .Net Runtime (v 8 or 10) and have my applications run natively on Android My understanding is that you can (almost) do that using MAUI (formerly known as Xamarin). You will not get a .Net SDK or Runtime, but the mono runtime. Since it is bundled in your app, you won't actually notice.

No, we need one level lower & zero mono. I want the sdk or runtime to be installed in the same way (and executable) the same way on android as on other linux distro's. .Net has ARM builds so it will work fine. This is without any specific framework dependencies (like aspnet, maui, avalonia etc) - just plain .net 8/10. It would actually be nice if android just bundled the runtime to begin with so we don't have to. The…

You can create Android apps in plain .NET, building Android UIs directly with C#

Re: Unity's Mono problem: C# code runs slower than it should

#184

Earlier quoted context omitted.

My main point is: if GDScript isn't good enough, go straight to c++ directly in the Engine. I won't even get into how big of projects I've written in GDScript successfully.

I don't want to do manual memory management and pointer handling I don't want to have any sort of undefined behavior I want to have quick code reload button in the editor I want to still rely of the engine official documentation with examples like it is with GDScript and C#

You likely won't need to do manual memory management nor think about undefined behavior. If your writing basic c++ to handle the simulation in a game, it's going to be pretty orthodox and these problems likely won't manifest.

The purpose of recommending c++ here is:

If GDScript is too slow, reach directly for C++.

I'm specifically recommending GDScript over C# for ease of use and c++ over C# for performance.

Re: Unity's Mono problem: C# code runs slower than it should

#185
post #164

Earlier quoted context omitted.

"not having a JIT" is not a problem, it's you speculating that a JIT will improve performance, the real problem is "GDScript has poor performance", which in this context (me saying C# in godot sucks) is you speculating that C#'s performance is better than GDScripts. Do you have any data to back that claim up? Like real world data from a real product? Or are you just speculating with vibes? If performance is a concern…

Some people like nice tooling with performance. Interpreter code is never faster than a dynamic compiler, otherwise what about doing games in Python? As mentioned on my comment, GDextension experience kind of sucks.

Lots of excellent games are written in Python, Lua, JavaScript and GDScript. These abstract criticisms are just that, abstract.

I'm offering real practical advice from experience of having worked on real projects.

I'll make it real clear:

GDScript & c++ > C#

Re: Unity's Mono problem: C# code runs slower than it should

#186
post #164

Earlier quoted context omitted.

Some people like nice tooling with performance. Interpreter code is never faster than a dynamic compiler, otherwise what about doing games in Python? As mentioned on my comment, GDextension experience kind of sucks.

Lots of excellent games are written in Python, Lua, JavaScript and GDScript. These abstract criticisms are just that, abstract. I'm offering real practical advice from experience of having worked on real projects. I'll make it real clear: GDScript & c++ > C#

[deleted]

Re: Unity's Mono problem: C# code runs slower than it should

#187

My dream would be that I can adb into my phone, install the .Net SDK or .Net Runtime (v 8 or 10) and have my applications run natively on Android. Simple console apps first, then the rest. Google should open their platform up a little bit more. Allow us to enable root access via adb. Let us unleash our pocket computer's full potentials. Would love to have portable low powered servers, running stacks of my choice. The…

I believe the root constraints are a security thing. They don't want you to charge your phone in a dodgy USB outlet in a public space (e.g. an airport) and be compromised. Making you flash your phone to get root is meant to prevent people accidentally exposing themselves.

Google can provide a non-rooted system image out of the box for safety, but nothing stops them from providing a clean & rooted image for download that I can flash onto device if needed.

The security model should already be tight enough so that a dodgy usb outlet does not compromise the core system (rewriting system images).

Re: Unity's Mono problem: C# code runs slower than it should

#188

Earlier quoted context omitted.

No, we need one level lower & zero mono. I want the sdk or runtime to be installed in the same way (and executable) the same way on android as on other linux distro's. .Net has ARM builds so it will work fine. This is without any specific framework dependencies (like aspnet, maui, avalonia etc) - just plain .net 8/10. It would actually be nice if android just bundled the runtime to begin with so we don't have to. The…

So for whatever reason you want the .NET runtime over Mono - not sure why that is a hard requirement, but AFAIK that is also the goal for microsoft. As in, merging those runtimes and have a single codebase that works for all platforms (including android). There are technical obstacles and historic codebases, but I would expect this unified runtime soon.

Cause since .Net Core 3 (first real production ready cross platformness) to .Net 10 (current LTS) is light years ahead of .Net Framework 4.8 / Mono (which is like half the performance of old .Net 4.8..). Not to be crude, but mono is pretty much trash. Should just be deprecated and the engine bro's should just stick to .Net LTS version (8 or 10, but 8 will be dead in a year). .Net 8/10 also has much better build tools, cleaner & smaller executables, better packaging tools to make deployments a breeze over the old system. The compiler is also much faster in general. You can tree-shake the hell out of your builds to get very lean artifacts. And then there is the garbage collector. And all of the low level optimizations in the CLR that just makes everything fast & less memory hungry.

Unity should really create a version of their engine on .Net 10, make the core as platform-agnostic as possible. It's fine if this variant is not backwards compatible. .Net 10 is also already on Xbox.

Re: Unity's Mono problem: C# code runs slower than it should

#189
post #183

Earlier quoted context omitted.

No, we need one level lower & zero mono. I want the sdk or runtime to be installed in the same way (and executable) the same way on android as on other linux distro's. .Net has ARM builds so it will work fine. This is without any specific framework dependencies (like aspnet, maui, avalonia etc) - just plain .net 8/10. It would actually be nice if android just bundled the runtime to begin with so we don't have to. The…

You can create Android apps in plain .NET, building Android UIs directly with C#

Its a pain though. We tried last year at work to build something a little bit more complex than their examples, and it was a pain. Gave up after a month and built our apps in Flutter instead. Works like a charm.

Re: Unity's Mono problem: C# code runs slower than it should

#190
post #183

Earlier quoted context omitted.

You can create Android apps in plain .NET, building Android UIs directly with C#

Its a pain though. We tried last year at work to build something a little bit more complex than their examples, and it was a pain. Gave up after a month and built our apps in Flutter instead. Works like a charm.

I’ve been building this way since 2018 using MvvmCross[0] and it's become much less painful with LLMs where you can simply ask to recreate an iOS UI on Android. I even managed to implement experimental hot reload[1] for native UIs on Android from .NET, but ended up not using it because, again, nowadays it's faster to iterate with Claude Code – it just one-shot things most of the time.

Currently I'm building an app with Uno Platform[2], which is basically .NET Flutter, and while it's cool to get things working across five different platforms at once, you can note the difference, especially on scroll. No automatic Liquid Glass / Material 3 for it either.

So it's a choose your poison situation: either building native interfaces on each platform separately, or fighting later with an additional layer of abstraction and a canvas-based UI wheel reinvention.

[0]: https://github.com/MvvmCross/MvvmCross

[1]: https://github.com/ivmirx/HotDemo

[2]: https://platform.uno/

Post reply on HN