Reproducing the Rust-versus-C++ byte counts =========================================== The census script in this folder (census.py) reads raw llvm-pdbutil dumps from a ./raw subdirectory. Those dumps are large and specific to a particular published PDB build, so they are not republished here; this file is the exact recipe that produces them, so the headline percentages can be checked rather than taken on trust. Everything below is free. Nothing here uses the PE viewer the article's screenshots come from. 1. Tools -------- symchk.exe Windows SDK, "Debugging Tools for Windows" feature. Typical path: C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\symchk.exe llvm-pdbutil.exe LLVM 21.1.4 was used here. Any recent LLVM release works. llvm-cxxfilt.exe Same LLVM install. census.py expects it at C:\Program Files\LLVM\bin\llvm-cxxfilt.exe (edit CXXFILT at the top of census.py if yours is elsewhere). python 3.11+ 2. Fetch the public PDBs ------------------------ Microsoft's public symbol server has a PDB for every binary in the census except NarratorMCAT.dll, whose PDB is named by cargo (libmathcat_c-.pdb) and is not on the server. set _NT_SYMBOL_PATH=SRV*C:\symbols*https://msdl.microsoft.com/download/symbols symchk /r "C:\Windows\System32\sudo.exe" /s %_NT_SYMBOL_PATH% symchk /r "C:\Windows\System32\UdiApiClient.dll" /s %_NT_SYMBOL_PATH% symchk /r "C:\Windows\System32\CloudRecoveryDownloadTool.dll" /s %_NT_SYMBOL_PATH% symchk /r "C:\Windows\System32\DWrite.dll" /s %_NT_SYMBOL_PATH% symchk /r "C:\Windows\System32\Narrator.exe" /s %_NT_SYMBOL_PATH% symchk /r "C:\Windows\System32\SRH.dll" /s %_NT_SYMBOL_PATH% symchk /r "C:\Windows\SystemApps\Microsoft.WindowsAppRuntime.CBS_8wekyb3d8bbwe\DWriteCore.dll" /s %_NT_SYMBOL_PATH% symchk /r "C:\Windows\SystemApps\Microsoft.WindowsAppRuntime.CBS.2_8wekyb3d8bbwe\DWriteCore.dll" /s %_NT_SYMBOL_PATH% Each lands at C:\symbols\.pdb\\.pdb. pdb-symbol-census.txt records a short PDB signature PREFIX beside each headline number (92A5ED42 for DWriteCore 2.1.1, for instance). That is a prefix, not the full GUID-and-age string symchk uses for the directory name, so treat it as a quick check that you are on the same build rather than as a complete identifier. If Windows Update has moved on, your GUIDs will differ and so may the counts; that is expected and is the reason every number in the article is tied to build 26200.9168. 3. Dump the four streams per PDB -------------------------------- census.py expects, for each PDB, four files in ./raw named by its short key: .modules.txt llvm-pdbutil dump --modules .publics.txt llvm-pdbutil dump --publics .symbols.txt llvm-pdbutil dump --symbols .seccontribs.txt llvm-pdbutil dump --section-contribs The short keys, and the binary each PDB belongs to, are the first column of the PDBS list at the top of census.py: dwritecore161 DWriteCore.dll, Windows App SDK 1.6.1 (inbox) dwritecore211 DWriteCore.dll, Windows App SDK 2.1.1 (inbox) dwrite System32\DWrite.dll (negative control) sudo System32\sudo.exe udiapi System32\UdiApiClient.dll cloudrecovery System32\CloudRecoveryDownloadTool.dll narrator System32\Narrator.exe srh System32\SRH.dll For one PDB, with %PDB% set to its full path: mkdir raw llvm-pdbutil dump --modules "%PDB%" > raw\sudo.modules.txt llvm-pdbutil dump --publics "%PDB%" > raw\sudo.publics.txt llvm-pdbutil dump --symbols "%PDB%" > raw\sudo.symbols.txt llvm-pdbutil dump --section-contribs "%PDB%" > raw\sudo.seccontribs.txt Repeat for the other seven, substituting the short key. 4. .text sizes -------------- census.py carries the .text VirtualSize of each binary as the last field of its PDBS entry. Note carefully what the headline percentage is a percentage OF: it is the Rust share of ATTRIBUTED code contributions, not of .text. For DWriteCore 2.1.1 the attributed contributions sum to 1,913,201 bytes, which is 98.7% of the 1,938,833-byte .text VirtualSize; the remainder is alignment padding and linker-generated bytes belonging to no contributing object. So Rust is 57.9% of attributed contributions and about 57.2% of .text. The column in the code-bytes files is named pct_of_attributed for exactly this reason. Confirm the .text sizes against your own copies with: llvm-readobj --sections "C:\Windows\System32\sudo.exe" and read VirtualSize for the .text section. These are properties of the shipped binary, not of the PDB. 5. Run it --------- python census.py It writes pdb-symbol-census.tsv, the per-PDB crate and code-byte files, the DWriteCore 1.6.1-to-2.1.1 diff, the Narrator math-symbol search and verification.txt. All of those outputs ARE published in this folder, so a successful run should reproduce the files sitting beside this one. verification.txt is the part worth reading first: it re-derives the parsed counts against raw grep counts on the dumps (for example, parsed publics versus `grep -c S_PUB32`), so a silent parsing failure in the symbol tables shows up as a MISMATCH rather than as a plausible wrong number. It is a cross-check on the public-symbol parse, not a proof that every section contribution parsed correctly. 6. What the measurement is, and is not -------------------------------------- It is the linker's own attribution: each attributed code byte is mapped to the object file that contributed it, and rustc's object is identifiable because link-time optimisation puts the whole Rust half of a binary in a single *.rcgu.o module. It is not a source-line count and cannot be compared with one. Identical-code folding can merge a small number of functions across the language boundary; verification.txt bounds that. Public PDBs carry no types, no line information and no inlined functions, so every function count here is a lower bound. The byte counts are complete for the contributions the linker attributed, which is slightly less than all of .text (see section 4).