T01, one line through ten stages - #39
Merged
Merged
Conversation
The first lesson of the tour. It takes one line of C#, follows it through the five stages that happen on the build machine and the five that happen on the machine running the program, and shows the evidence for each one out of the file or out of the live process. Fourteen blocks, all E0, no C++ and no debugger. Four of them are dropped from the page because what they print is a property of the machine rather than of .NET, and each of those carries assertions instead. Also turns off the trimming, AOT and single file analysers for lessons. A lesson is never published, half of what these lessons do is reflection, and left on they printed five warnings ahead of the first line of output. A lesson about trimming turns them back on in its own directory.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The first lesson of Part I. It takes one line of C#,
public static int Count(string line) => line.Split(' ').Length;, and follows it all the way down.Ten stages. Five of them happen on the machine that runs the build and five happen on the machine that runs the program, and the split between those two halves is the thing the lesson is actually for. Almost everything people find confusing about .NET sits in that gap.
What is in it
Fourteen blocks, all E0. No C++, no debugger, no privilege a reader does not already have. It is
System.Reflection.MetadataandSystem.Reflection, both of which ship in the box, pointed at a small fixture program next door.The evidence for each stage comes out of the file or out of the live process rather than out of my memory. The overload the compiler picked is read back out of the signature blob. The claim that there is no machine code in the assembly is the
ILOnlyflag and a zero sized directory, both printed. The claim that the launcher contains none of your code is two byte searches over the launcher and two over the assembly. The claim that the JIT runs on first call is a timing, and the claim that a line with nonewin it allocates five objects is the per thread allocation counter, measured one allocation at a time so the arithmetic on the page comes from the machine rather than from me.Three prediction gates: what the CPU field in the header says, how many arguments the IL call passes, and how many objects reach the heap. Every option carries a written explanation, including the wrong ones.
One diagram,
docs/diagrams/ten-stages.dg, with the build row along the top and the run row along the bottom.The four dropped blocks
Four blocks are marked
capture=drop, so the page cannot quote them. The file sizes move with every SDK. The JIT timings are a function of the machine and the weather. The type handles and the entry point are addresses in one process on one run. The runtime version and platform are different by definition.Each of those carries assertions instead, ten in total, and every claim has a written reason. The load bearing one is
the first one cost at least ten times the rest. Ten is a long way below what any machine here actually shows, which is a few hundred, and it is set low on purpose so a busy shared runner does not turn a true statement red.The analyser change
lessons/Directory.Build.propsturns off the trimming, AOT and single file analysers.A file based app has them on, because the point of one is that
dotnet publishcan turn it into a native binary. A lesson is never published. It runs once during the build and once for a reader, and a good deal of what these lessons exist to show is done through reflection, which is exactly what those analysers warn about. Left on, this lesson printed five warnings before it printed anything a reader wanted, and warnings nobody can act on are how people learn to scroll past warnings.A lesson that is about trimming or AOT turns them back on in its own directory, and Part IX is where that happens.
Checked
xray build,xray check,xray numbers,xray assert,xray lintanddotnet format --verify-no-changesall clean locally on osx-arm64.Also run on server3, linux-x64, against the committed expected output, because a first lesson with nine captured outputs is exactly the kind of thing that turns out to differ on the second platform. It matched byte for byte. The remaining two platforms are on CI.
Not in this PR
No
runtime:citations, becausepin.jsonstill holds a null commit and this repository refuses a citation it cannot resolve to one. Everything claimed here is either a claim about the file format, checkable against ECMA-335, or a claim about behaviour, checkable against the output on the page. Z01 through Z03 are waiting on the same pin, which is why the tour starts at T01 rather than at the top of the issue.No boss fight. T10 is the chapter boss for Part I.