1

To me, merging .Net binaries so that I'm left with one single file executable was always a both interesting and important feature. From what I've read, there are three approaches regarding this:

  1. ILMerge

    • Really merges the assemblies. Comparable to creating one single .csproj and pulling in all source code.
  2. Fody.Costura

    • Keeps the assemblies seperate but just includes their files as ressources and bends the resolution accordingly.
  3. .Net Core 3+ PublishSingleFile / Warp

    • From what I understand the approaches are similar. Extract the files to a temp dir on first execution and just run them normally.

While the topics are quite related and sometimes do overlap I don't intend to mix up single file, self-contained deployments and trimming - I'm mainly thinking of the single file part here.

I think any of the three approaches has it's own advantages and disadvantages and no one is "the" way to go.

  1. ILMerge

    • + Seems like the most natural option for "merging"
    • + Requires no runtime loading, if everything is there and works than that's it; once the image is in memory we're done
    • - Loading everything at once everytime might lead to lower startup performance, relevant to desktop apps
    • - Changes quite much about the internals, assembly names change, probably library internals get more involved with app code etc.; this might lead to hard to debug errors, in the worst case popping up in production, I guess. It just changes things developers may have taken for granted (i.e. name of their assembly).
    • - Probably not conceptual but doesn't support .Net Core => dealbreaker
  2. Fody.Costura

    • + Enables compression for dependencies
    • + Changes much less internals, probably leading to less unforeseen situations
    • + Probably requires the OS to load the full image but not the CLR to load the libs at once so might improve start-up performance
    • - Requires de-gzipping the dependencies every time; might be a performance penalty CPU-wise, could be a performance benefit IO-wise
  3. Self extracting

    • + Compressed too
    • + Once the code is extracted and running, the only difference is where it's located. Thus, lib developers can even still find their assembly on disk etc., making the least runtime differences I guess.
    • - First time startup can take some noticable time and is quite IO intensive, kind of an installation.
    • + Subsequent runs behave like non-single-file deployments, having their respective (dis)advantages compared to the other two.
    • - Comes with some non trivial problems. When to update the extracted files? Who deletes old versions of the extracted files? What if the disk is full/...?
    • - Executing is not side-effect free anymore.
    • - More then 2x the disk space needed.

In my personal obviously non-exhaustive and non-scientific experience, (3) sometimes had some rough edges and showed strange behaviour while (2) worked really good in the years I've been using it (comaring Framework vs Core though). But probably thats either due to the implementation of (3) beeing quite new or my misunderstanding.

The intention of me posting this question is to (a) understand this better in general and (b) understand why Microsoft chose (3). So, it'd be great

  • if I missed differences between the three to point them out (feel free to edit the question to keep things in one place).
  • if I made false assumptions to point them out.
  • if there are more options in general or if I'm wrong about one of the concepts to point them out
  • if there's content about the reasoning, why Microsoft selected (3) as the superior way (that would probably deepen my understanding for the pros and cons) to point me in the right direction.

While I understand it's hard to compete with a framework feature, I'm a bit sad that Costura is in maintenance mode, given I think it has advantages over the frameworks approach, making the second option a viable choice. Thus, one of the reasons I'm asking this question is to understand if there are any severe advantages of (3) over (2) I'm overlooking.

Georg Jung
  • 949
  • 10
  • 27
  • 1. Before shipping .NET Core 3.0's single file approach (the one you described as option 3), there were discussions around which way to go, like https://www.hanselman.com/blog/BrainstormingCreatingASmallSingleSelfcontainedExecutableOutOfANETCoreApplication.aspx and other threads. The choice made then was a balance between usability and time-to-market, not necessarily the optimal. 2. There can be better options (no, your option 1/2 above are dead-end), like what Go and other languages do, which Microsoft can implement but need more resources/time. – Lex Li Apr 11 '20 at 14:19
  • What would those other options look like? You think of something like AoT and static linking? Why are one and two dead ends, conceptually? – Georg Jung Apr 11 '20 at 14:25
  • Not easy to compile all previous discussions in a few words, but AOT/static linking should be the best. ILMerge is too old a code base to move forward. Fody.Costura probably is not debugging friendly (like breakpoints/Edit-and-Continue). Microsoft almost always puts higher priority on ease of debugging, so that rules out many approaches. – Lex Li Apr 11 '20 at 14:46
  • 1
    Links such as https://github.com/dotnet/designs/blob/master/accepted/2020/single-file/staging.md contain background information you might need, but I believe it would be rather complicated to collect all necessary pieces you wanted above. – Lex Li Apr 11 '20 at 14:53
  • Ah, thank you for providing this link, it's kind of what I was looking for. Specifically, I didn't know there is a roadmap for taking this further - that's quite interesting. (2) or (4) of the doc would probably be kind of what I was hoping for and bring some of Costura's advantages to the framework's approach. Thanks! Do you know if there's any timeline for that/which parts of this we will see in .Net 5.0? – Georg Jung Apr 11 '20 at 18:49
  • > "to compile all previous discussions in a few words," If you have more of those interesting links I'd be quite interested too, no need to write all the stuff again. – Georg Jung Apr 11 '20 at 19:03
  • Ah, reading the files in the same folder I've noticed the roadmap I asked for is right there, sorry: https://github.com/dotnet/designs/blob/master/accepted/2020/single-file/design.md – Georg Jung Apr 11 '20 at 19:06

0 Answers0