-- Leo's gemini proxy

-- Connecting to gemi.dev:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini

Unexpectedly Faster .NET execution for my CGIs

2023-01-11 | #programming | @Acidus


I primarily write code in C#, and all the CGIs here like Gemipedia, NewWaffle are written in C# on a Mac. My capsule runs on a simple Linux VPS. Luckily .NET code is cross platform. I use "make" to build the CGI programs and rsync them to my capsule.


Without getting to much into the specifics of .NET and building/publishing apps, there are 2 broad ways to publish an app


Publishing your app as "self-contained" produces an application that includes the .NET runtime and libraries, and your application and its dependencies. Users of the application can run it on a machine that doesn't have the .NET runtime installed.


Publishing your app as "framework-dependent" produces an application that includes only your application itself and its dependencies. Users of the application have to separately install the .NET runtime.


When building my first CGI, I used "self-contained" approach to reduce the number of variables like the location of the .NET runtime, versions, permissions, PATH variables, etc. My understanding was, my executables would be bigger because each folder contained my code plus all the Microsoft code of the runtime. It took up more space, but I largely didn't care.


As I added more CGIs I just kept copy+pasting the same Makefile lines over and over again, and didn't really think much of it.


Except now I have 6 CGIs (plus some programs for offline tasks) and sending 6 different copies of the .NET runtime (or at least the parts that each CGI used) over and over seemed silly. rsync is fast, but sending 6x more data than you need to is silly. So I went ahead and setup .NET on my Linux VPS and moved to using framework-dependent builds


For other .NET developers out there, all I'm doing is:

dotnet publish -c Release -r linux-x64 --self-contained false $(codeDir)/NewsWaffle/NewsWaffle.Cgi/NewsWaffle.Cgi.csproj

My rsyncs were faster, but I also noticed about the executables themselves ran faster. Using "time ./NewsWaffle.Cgi" I see a 150ms difference on my VPS between executing the self-contained and framework-dependent approaches. This code path simply prints the main static page of NewsWaffle, without any serious CPU or any network requests. I see about 150ms difference


self-contained time: ~0.273s

framework-dependent: ~0.112s


I don't have a strong answer for the difference. I'm not Ahead-of-time JITing. I suspect it has to do with the overhead of opening the numerous and fragmented .NET runtime libraries that come with the self-contained app, but even then I would suspect that that disk access would be cached in RAM and not significantly different than the shared .NET runtime libraries. I'm not entirely sure.


Regardless of the source, it goes to show that:

Assumptions/short cuts you made early in a project should be revisited as situations evolve. Self-contained made sense originally, until it didn't.

Always test you code to make sure you aren't regressing in performance or UX. It's the only way to know if you are getting better

-- Response ended

-- Page fetched on Tue May 21 09:22:32 2024