Scott Hanselman

Speed of dotnet run vs the speed of dotnet for published apps (plus self-contained .NET Core apps)

June 28, '17 Comments [8] Posted in DotNetCore
Sponsored By

The .NET Core team really prides themselves on performance. However, it's not immediately obvious (as with all systems) if you just do Hello World as a developer. Just today I was doing a Ruby on Rails app in Development Mode with mruby - but that's not what you'd go to production with.

Let's look at a great question I got today on Twitter.

Dotnet Run - Builds and Runs Source Code in Development

That's a great question. If you install .NET Core 2.0 Preview - this person is on a Mac, but you can use Linux or Windows as well - then do just this:

$ dotnet new console
$ dotnet run

It'll be about 3-4 seconds. dotnet is the SDK and dotnet run will build and run your source code. Here's a short bit from the docs:

The dotnet run command provides a convenient option to run your application from the source code with one command. It's useful for fast iterative development from the command line. The command depends on the dotnet build command to build the code. Any requirements for the build, such as that the project must be restored first, apply to dotnet run as well.

While this is super convenient, it's not totally obvious that dotnet run isn't something you'd go to production with (especially Hello World Production, which is quite demanding! ;) ).

Dotnet Publish then Dotnet YOUR.DLL for Production

Instead, do a dotnet publish, note the compiled DLL created, then run "dotnet tst.dll."

For example:

C:\Users\scott\Desktop\tst> dotnet publish
Microsoft (R) Build Engine version 15.3 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

tst -> C:\Users\scott\Desktop\tst\bin\Debug\netcoreapp2.0\tst.dll
tst -> C:\Users\scott\Desktop\tst\bin\Debug\netcoreapp2.0\publish\
C:\Users\scott\Desktop\tst> dotnet run .\bin\Debug\netcoreapp2.0\tst.dll
Hello World!

On my machine, dotnet run is 2.7s, but dotnet tst.dll is 0.04s.

.NET Core is fast

Dotnet publish --self-contained

I could then publish a complete self-contained app - I'm using Windows, so I'll publish for Windows but you could even build on a Windows machine but target a Mac runtime, etc and that will make a \publish folder.

C:\Users\scott\Desktop\tst> dotnet publish  --self-contained -r win10-x64
Microsoft (R) Build Engine version 15.3 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

tst -> C:\Users\scott\Desktop\tst\bin\Debug\netcoreapp2.0\win10-x64\tst.dll
tst -> C:\Users\scott\Desktop\tst\bin\Debug\netcoreapp2.0\win10-x64\publish\
C:\Users\scott\Desktop\tst> .\bin\Debug\netcoreapp2.0\win10-x64\publish\tst.exe
Hello World!

Note in this case I have a "Self-Contained" app, so all of .NET Core is in that folder and below. Here I run tst.exe, not dotnet.exe because now I'm an end-user.

The results of a published .NET Core App

I hope this helps clear things up.

Sponsor: Check out JetBrains Rider: a new cross-platform .NET IDE. Edit, refactor, test, build and debug ASP.NET, .NET Framework, .NET Core, or Unity applications. Learn more and get access to early builds!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb
Thursday, 29 June 2017 01:44:09 UTC
I still don;t understand why you have to install IIS Hosting then publish a huge DLL filled web app to host? Can you go over that in detail but at a basic start to finish level?
Chris Go
Thursday, 29 June 2017 07:57:01 UTC
Is there some explanation as to why compiling and running a trivial program takes 3-4 seconds? I find that the most painful part of .NET Core development right now is developer iteration. Every time I make a change in an ASP.NET Core Controller and refresh the page or attach the debugger in a non-trivial program I'm sat waiting for 10+ seconds. My iteration times seems to have doubled or worse compared to the traditional .NET apps I'm working on.

It seems somewhat startling to me that a program with ~10 lines of code, most of which are usings, a namespace declaration, and braces, that probably compiles to no more than a hundred or so lines of IL, takes a modern multi-core machine 3-4 seconds to build.

To put that 3-4 seconds into context: the Jai language can parse, lex, compile, link, and output a program with 50k+ lines of code, using LLVM on the back end, and featuring build-time meta-programming and some other pretty complex language features, in just over half a second. No incremental builds or anything.
Steve Vallis
Thursday, 29 June 2017 08:35:47 UTC
One other thing you can do is set the environment variable DOTNET_CLI_CAPTURE_TIMING first, i.e.

Then you get some timing/diagnostic info printed out, see for some more info.
Friday, 30 June 2017 04:10:02 UTC
@Steve I agree. All this talk of pride performance feels like a reaction to complaints about performance. I'm finding the .NET Core space wildly confusing. Layer on top of that Angular and you have the perfect vortex of uncertainty, confusion and spinning wheels.

At the operating system level, Windows is doing the convergence thing which is another bad direction. Maybe I'm getting old. But Windows 7 is still the best version of Windows available. Glad to see Ubuntu jettison Unity. At least they've seen the light and are taking non-PC form factors out of the equation.

On a related note, a lady did a presentation at my local user group on Holo-lens. She enthusiastically asked, "How many people are developing UWP apps?" ** Tumbleweeds and sniggers **
Friday, 30 June 2017 06:15:28 UTC
You can also add --no-build to dotnet run command "dotnet run --no-build"
Friday, 30 June 2017 06:41:18 UTC
Great Post Scott, Thanks!
Jhon Montenegro
Saturday, 01 July 2017 20:04:49 UTC
Is it self contained? Don't you need a CLR or something?
Saturday, 08 July 2017 14:38:38 UTC
Hi Scott,

Does the --self-contained flag mean that the code is going to be pre-JITted during the publish step or just that it's packaged in one dll?
Do you know if this flag will also work for ASP.NET Core?

Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.