Runtime: Proposal: Get rid of "checked" build flavor

Created on 6 Feb 2020  路  25Comments  路  Source: dotnet/runtime

checked build flavor is a foreign concept that takes a lot of explaining and causes unnecessary complexity.

The checked build flavor (ie build with asserts and optimizations on) is left-over from razzle (the original Windows OS build environment). I believe most project still on razzle (including Windows OS) got rid of it and have just debug (that is built with optimizations on by default) and release.

If developers want to compile the code with C/C++ optimizations off to get better debugging experience, they can pass an extra argument to the build script to turn off the optimizations. It is conceptually no different from e.g. a build script switch to use a different C/C++ compiler for the build.

Should we adopt this for CoreCLR build?

area-Infrastructure-coreclr

Most helpful comment

I always use debug build and use checked only in cases where I need to get slightly better perf, like when running coreclr tests suite. On Linux, debugging coreclr with any optimizations is pretty painful. While on Windows you can easily debug even release build, on Linux you get virtually no locals, no parameter values etc. Even checked is quite bad on Linux.
So if we made debug == checked, I would need to have a command line option in the build scripts that would allow me to disable optimizations. But I agree that separate checked / debug flavors are probably not necessary from all the other points of view.

All 25 comments

If I'm understanding correctly, this isn't exactly removing checked; rather it's getting rid of debug and renaming checked to debug, is that right?

Yes, that's right.

Sounds good to me, but I also almost never build coreclr as debug, only checked and release.

I always use debug build and use checked only in cases where I need to get slightly better perf, like when running coreclr tests suite. On Linux, debugging coreclr with any optimizations is pretty painful. While on Windows you can easily debug even release build, on Linux you get virtually no locals, no parameter values etc. Even checked is quite bad on Linux.
So if we made debug == checked, I would need to have a command line option in the build scripts that would allow me to disable optimizations. But I agree that separate checked / debug flavors are probably not necessary from all the other points of view.

Yes, a command line option to turn off optimizations for C/C++ would be part of the plan.

If we do this we should also clean-up the checked conditions in System.Private.CoreLib in mono: https://github.com/dotnet/runtime/blob/1a1a541954db674980b09efe426d3b6dfd6ae3c9/src/mono/netcore/System.Private.CoreLib/System.Private.CoreLib.csproj#L90-L92

I assume that we align configurations so that they are doing the same thing on Mono and CoreClr.

I鈥檓 with @janvorli on this; I always use Debug. I only use checked when reproing test failures so I match what CI is doing. As long as there鈥檚 an option to disable optimizations in debug, I鈥檒l be satisfied.

What is the advantage of removing checked? If you want unoptimized binaries with the best debugging experience, you'll need to use a new option, which might confuse your builds. E.g., it might be more confusing in your artifacts directory to know what is optimized and what is not.

I run Debug when debugging, but Checked when running tests. With the new proposal, I would need to go back-and-forth, rebuilding with and without the new flag into the same artifacts location (presumably) to be able to do this. That seems very wasteful.

@dotnet/jit-contrib

I totally agree with what @BruceForstall says about wanting to understand the advantages (and the trade-offs). I use Checked most of the time, but will occasionally build Debug when optimization gets in my way. Whatever we do it needs to be friction-free to accommodate varying requirements.

Does the proposal include the possibility of building code without assert yet unoptimized?
This flavor could be useful when the asserts are getting in the way diagnosing problems.

My experience for checked builds is that debugging them is less than great, but as long as I can remember the magic incantation for disabling optimization on a per file basis, I'm able to make good progress.

For clang its

#pragma clang optimize off

For msvc its

#pragma optimize("", off)

I just stick those at the top of the files I'm mostly working in, and checked builds become more reasonable to debug.

@davidwrighton - while disabling optimization on a per-file basis may work I would not describe it as friction-free for development.

FWIW, what I often do when debugging the JIT and the optimizer gets in my way is to build Debug and copy just the debug JIT over to a checked build.

FWIW I almost never use debug builds, so I'd be ok with making the "new debug" == "old checked".

In prior systems I worked on we had the notion of a custom build path, you could basically create arbitrarily-named artifact subtrees for your custom builds. Though it seems like in our system the available build types leak into scripts and this is less feasible. Maybe we can keep the current no-opt debug with its own artifact trees -- just give it a new name?

Maybe we can keep the current no-opt debug with its own artifact trees -- just give it a new name?

Can we instead adopt CMake terminology that should be clear for everyone:

  • Debug
  • Release
  • RelWithDebInfo

Those cmake terms don't (I believe) capture what we do for Debug/Checked/Release. For us, Release is always built with debug info. And Checked has asserts enabled.

I really like @echesakovMSFT鈥檚 suggestion. We should follow standard terminology when possible. Also, it would help simplify our CMake scripts a little, and would help simplify onboarding to the repo for new developers.

I really dislike the RelWithDebInfo. I would never want to type that in.

What is the advantage of removing checked?

It is the special CoreCLR-specific thing that I keep seeing leaking to number of other places in the overall dotnet/runtime experience and scripts. FWIW, this is what inspired me to write this proposal: https://github.com/dotnet/arcade/pull/4764#discussion_r375809945

a custom build path, you could basically create arbitrarily-named artifact subtrees for your custom builds.

Yes, having this would be nice. The artifacts path is hardcoded to repo_rootartifacts in number places. I have been working around it by renaming artifacts directory back and forth as necessary. I do not actually care about debug vs. checked most of the time. I just need to have different custom builds around SxS.

I actually think of Checked as ReleaseWithAsserts so a know to turn on checking in Release makes more sense to me. Some of the checks are more expensive than other so having degrees of checking might also be useful. (On Arm64 a few tests slowed down several orders of magnitude because of heap checking too often.)

Looks like this was done as part of https://github.com/dotnet/runtime/issues/35202?

It was not.

@dotnet/jit-contrib The JIT team is a heavy user of Checked builds.

Problem was on our end. Thanks for the confirmation. :)

Was this page helpful?
0 / 5 - 0 ratings