8 ms·
Introducing .NET IL Linker
- bernadus_edwin 9y agoIs java has linker feature?
- pjmlp 9y agoYes, shipping on Java 9.
- christophilus 9y agoIt's been a few years since I used .NET, but the self-contained deployment story sounds like a big win that I used to really want: "Self-contained deployment. Unlike FDD, a self-contained deployment (SCD) doesn't rely on the presence of shared components on the target system. All components, including both the .NET Core libraries and the .NET Core runtime, are included with the application and are isolated from other .NET Core applications. SCDs include an executable (such as app.exe on Windows platforms for an application named app), which is a renamed version of the platform-specific .NET Core host, and a .dll file (such as app.dll), which is the actual application." So, this IL Linker is in support of that story, and aims to reduce the over all size of self-contained applications... Maybe it's time to start tinkering w/ .NET again.
- danek 9y agoMy company has some apps that we need to install on our customers servers. A linker would have been amazing for us 7 years ago as we could have targeted the (as of then new) 4.0 runtime and redistributed or binary. But as it was, we could only expect the 2.0 runtime to be installed so we can't really leverage a lot of stuff that's been out since then and had to write our own hacky versions of lots of common things. Nowadays with dotnet core you can bundle the entire runtime with you binary. The linker is cool, in that it will create a strictly smaller binary, as in "hello world" might be 12mb instead of 50mb. That's cool, but it makes me wonder if .NET would be in a strategically better place today if the linker were present 10 years ago. How many companies didn't choose to write their app in c# simply because a customer might not have the runtime installed? In any case I'm really impressed with everything Microsoft is doing with dotnet core and hope that I get to use more of it.
- therein 9y ago> How many companies didn't choose to write their app in c# simply because a customer might not have the runtime installed? More than enough to make a difference against Java.
- deleted 9y ago[deleted]
- int_19h 9y agoIt certainly would. The reach of .NET was artificially restricted in many respects by making it a component of Windows. Mono provided the ability to just ship the runtime alongside the app, but Mono was also not "enterprise grade"; and of course there were always the missing bits and pieces, especially on the desktop front where such deployment made most sense. It took a Microsoft that understood open source and non-Windows platforms, and was serious about it, to ultimately get us to the point where .NET Core could be a thing.
- pjmlp 9y agoUntil .NET Core provides support for many of the .NET Framework APIs still lacking from .NET Standard 2.0, many companies won't consider it "enterprise grade". Examples on our case, WPF, WCF, ODP.NET drivers for ADO.NET.
- svick 9y agoI think .Net Core will never include WPF. As far as I know, there are not plans for cross-platform GUI on .Net Core. And WPF is pretty much a dead technology.
- mr_overalls 9y agoI really want C#/.NET to gain ground against Java. I started my career working for a .NET shop a few years ago, and immediately fell into a love/hate relationship with the technology stack. I loved C#, as it seemed to be a fantastically well-designed language that had learned a lot from Java's mistakes. Visual Studio was great, too. However, as a longtime Linux and open source supporter, I loathed Windows and Microsoft's software culture. And honestly, the .NET open source culture - even now - is kind of lacking. C# shops typically wait for some canonical solution from MS rather than creating and sharing libraries themselves. I really, really like the new direction that Microsoft is taking, and I hope that the open source community will embrace C# in a bigger way.
- james-skemp 9y ago.NET for over a decade and "C# shops typically wait for some canonical solution from MS" rings quite true. With NuGet I don't think it's as bad as it was, but I just caught myself hesitating when I found out this week that .NET has deprecated email sending functionality in 4.7 (or Core?) and is now recommending open source alternatives.
- neilsimp1 9y agoRelevant Scott Hanselman blog post: https://www.hanselman.com/blog/ExperimentalReducingTheSizeOfNETCoreApplicationsWithMonosLinker.aspx https://www.hanselman.com/blog/ExperimentalReducingTheSizeOf...
- blinkingled 9y ago> And, it wouldn't be right to announce this linker without a hat tip to Joel Spolsky who we can give the honorary and historical distinction of feature requestor. https://www.joelonsoftware.com/2004/01/28/please-sir-may-i-have-a-linker/ https://www.joelonsoftware.com/2004/01/28/please-sir-may-i-h... - Joel asked for this in 2004 - Better 13 years late than never!
- pcunite 9y agoIf .NET (using C#) can produce a native binary I'll switch to that for as many projects as I can. Currently I use C++, mostly to interface with the OS. I love the feel I get when working in C#. Everything is so nice and cozy. Memory: The memory usage "looks" bad. I suppose maybe GC would kick in when it needs to. It has not been a problem for me, but when you see the code in C++ taking 1MB ram and a C# implementation taking 10MB, well, you have to wonder. Performance: C# performs bounds checking, which I take it is a significant performance hit. I've not had this matter yet, but I've not converted everything over to .NET.
- judah 9y agoThere's definitely a cost to all that coziness; it's all about tradeoffs. Garbage collection, bounds checks, APIs that trade memory efficiency for ease-of-use, to name a few. It's not to say that C# will always be 10x memory usage, however, it will always be somewhat higher. Even with a linker, when you run a .NET app, it's not just loading your C# code, but also .NET code that you call into (linker helps keep this slim) and of course the Common Language Runtime C++ code that executes your app and manages its memory.
- svick 9y ago> APIs that trade memory efficiency for ease-of-use This is currently being worked on. With the addition of Span<T>, many APIs will soon have a version that does not allocate and instead use a buffer you pass in (which can be managed or unmanaged).
- ZenoArrow 9y ago> "If .NET (using C#) can produce a native binary I'll switch to that for as many projects as I can." https://docs.microsoft.com/en-us/dotnet/framework/net-native/ https://docs.microsoft.com/en-us/dotnet/framework/net-native...
- jetti 9y agoI like how Microsoft added this but the major drawback is it is Windows 10 only.
- sharpercoder 9y agoI thought this technique of eliminating dead code was called tree-shaking. And linking to be something entirely different: linking assemblies at (compile|run|analysis)-time.
- mitchty 9y agoI've only ever heard it called dead code elimination. Tree shaking appears to be more a javascript thing? Not sure I don't participate in that community at all. https://en.wikipedia.org/wiki/Dead_code_elimination https://en.wikipedia.org/wiki/Dead_code_elimination
- cwzwarich 9y agoIt's an old Lisp term going back decades. Strictly speaking it's not the same as interprocedural DCE, because due to the dynamic features of Lisps you might need the user to specify the extent to which they are willing to disable the dynamic features to save space.
- mitchty 9y agoGotcha, would it be fair to characterize it as tree shaking is more white listing things that have been used versus eliminating code paths that cannot be accessed?
- algorithmsRcool 9y agoYes dead code elimination is also called tree shaking and it is typically done at compile time. However for .NET, since you can use reflection to load any type in an assembly and call any method dynamically, removing a method is isn't statically called could cause you to fail at runtime. Since reflection and dynamic invocation is a major feature of the runtime, they have avoided this optimization before.
- SideburnsOfDoom 9y ago> However for .NET, since you can use reflection to load any type in an assembly and call any method dynamically, removing a method is isn't statically called could cause you to fail at runtime. Indeed. it's not that common, but I would expect it to happen. One example is that many IoC Containers allow you to scan assemblies and register all class + interface pairs that match given rules. There has to be some safety-hatch to express "yes, I really want to keep that class and its methods. Don't strip them out". This seems to be documented here: https://github.com/dotnet/core/blob/master/samples/linker-instructions-advanced.md#limitations https://github.com/dotnet/core/blob/master/samples/linker-in...
- userbinator 9y agoGoing from over 46MB to under 12MB seems impressive on a relative scale, but if this is the code of the "dotnetapp-selfcontained" example, https://github.com/dotnet/dotnet-docker-samples/blob/master/dotnetapp-selfcontained/Program.cs https://github.com/dotnet/dotnet-docker-samples/blob/master/... That is still, absolutely speaking, twelve million bytes for not much more than "Hello World" levels of functionality, which means there remains plenty of room for improvement. I estimate the lower limit for this particular app is somewhere in the hundreds of bytes, most of it being string constants.
- judah 9y agoI see this fallacy repeated often. "Hello World is 12 MB - just imagine how big a real app will be!!!" Hello World doesn't benefit from that 12MB. Your real app would. 12MB is not for Hello World. 12MB is for Hello World + Common Language Runtime (garbage collection, bounds checking, memory protection, execution environment etc.) + the .NET standard libraries (LINQ, task parallel library, etc.) You're probably going to need those things in a real app. If you're actually doing Hello World -- and that is all you're doing -- and if using 12MB of your 16GB of RAM is unacceptable for you, yes, by all means write some native code.
- algorithmsRcool 9y agoPut another way: what should be left after linking is just the parts of the CLR + BCL that the runtime needs to function. Apparently that takes 12MB today. There is a JIT, GC and Execution Engine all in there. The number might shrink as the linker gets more aggressive but i wouldn't count on it much. The application IL code is perhaps 50 bytes to for hello world.
- Kuraj 9y ago12 megabytes doesn't sound too bad for the things you mentioned, especially if it's a constant cost.
- svick 9y ago> The application IL code is perhaps 50 bytes to for hello world. A Hello World assembly in .Net Core 2.0 is 4.5 kB. Out of that, the IL is 11 bytes, though that doesn't even include the "Hello world!" string.
- marssaxman 9y agoI wonder how this interacts with the "no-PIA" feature, where the compiler would embed and dead-strip COM interop types. Seems like some of that system's guid-based type identity attributes might be relevant.
- svick 9y agoThis is (at least for now) only for .Net Core, which does not support COM interop, I believe.
- 64738 9y agoCan you create a self-contained deployment (SCD) of a GUI app, or does it only work for console apps?
- runfaster2000 9y agoWe currently have no GUI story for .NET Core. At the point that one gets added, yes, this will totally work.
- mellinoe 9y agoThe technology will work with any kind of app. I know that some folks working on one of the bigger UI frameworks, Avalonia (https://github.com/AvaloniaUI/Avalonia https://github.com/AvaloniaUI/Avalonia) have toyed with it recently. One thing to keep in mind is that lots of these frameworks do dynamic, reflection-based data binding, which might be easily broken if the linker removes too much stuff. You can tinker with the settings of the linker to force it to preserve things that are actually necessary.
- jbevain 9y agoFun fact, the Mono Linker project started 10 years ago during the second edition of the Google Summer of Code! It was originally used to reshape the entire Mono class library into a subset to expose the Silverlight class library API surface for Moonlight. It was then used to link iOS and Android applications in MonoTouch and Mono for Android, and Xamarin continued to use and improve it. The Mono Linker has an open architecture making it reasonably easy to customize how it processes code , and detect patterns specific to each platform to link them away. Xamarin added linker steps to do more than tree-shaking, and remove dead code inside methods. For instance: if (TargetPlatform.Architecture == Architecture.X64) { // .. } The entire if body can be removed if the linker knows that TargetPlatform.Architecture will not be X64. And now, it's the base for the .NET Core linker. Quite a journey!
- caleblloyd 9y agoThis is neat as it brings smaller DLL sizes. It does not include self-contained executables that can be shipped, however. You still end up having to ship a directory full of DLLs. I've been wanting self contained executables for a while now. CoreRT (.NET Native) seems to have been put on the backburner, plus sometimes the JIT case is faster. Source: discussion at https://github.com/dotnet/core/issues/915#issuecomment-326081258 https://github.com/dotnet/core/issues/915#issuecomment-32608...
- joshschreuder 9y agoNot sure about .NET Core as I haven't used it yet, but you can use ILRepack to merge DLLs into the executable so you don't need to ship a directory full. https://github.com/gluck/il-repack https://github.com/gluck/il-repack We do this at work with one of our utilities
- tjalfi 9y agoCostura[0] embeds assemblies within a .NET executable. I have used it successfully for several projects at work. [0] https://github.com/Fody/Costura https://github.com/Fody/Costura
- svick 9y ago> CoreRT (.NET Native) seems to have been put on the backburner It looks fairly active to me: https://github.com/dotnet/corert/graphs/contributors https://github.com/dotnet/corert/graphs/contributors
- revelation 9y agoNow they just need a modern (XAML, QML) cross-platform UI story and they can eat Qt and Electrons lunch.
- mellinoe 9y agoThere's a few projects working in this direction, one of the coolest being Avalonia (IMO, at least). It's still in "alpha", although I heard a beta was not far off. https://github.com/AvaloniaUI/Avalonia https://github.com/AvaloniaUI/Avalonia
- Ciantic 9y agoHere is discussion and issue [1] it might be something they implement on .NET Core 3.0. Not very soon though, but this is a big ship, and it takes a long time to turn it. https://github.com/dotnet/designs/issues/12 https://github.com/dotnet/designs/issues/12
- ledgerdev 9y agoMS/Xamarin is working on XAML Standard implementations for Win/Mac/GTK. https://blogs.windows.com/buildingapps/2017/05/19/introducing-xaml-standard-net-standard-2-0/ https://blogs.windows.com/buildingapps/2017/05/19/introducin...
- manigandham 9y agoNice to see this progress, hopefully it's a serious part of the roadmap and not just a side experiment.
- Nuzzerino 9y ago> "The linker removes code in your application and dependent libraries that are not reached by any code paths. It is effectively an application-specific dead code analysis." Putting aside the discussion on whether this is a good practice, I assume this would remove methods that are only called dynamically, or via reflection.
- danek 9y agoI'm also curious how this would work without breaking reflection
- matthewwarren 9y agoThey talk about this here https://github.com/dotnet/core/blob/master/samples/linker-instructions-advanced.md#limitations https://github.com/dotnet/core/blob/master/samples/linker-in...
- danek 9y agoThank you
- flukus 9y agoDon't forget to check the license of every library, even many of the more permissive ones will require an attribution notice.