Professional Documents
Culture Documents
In the previous episode of Simple Changes to Shrink Chrome I discussed how deleting
const from a few key locations could lead to dramatic size savings, due to a VC++
compiler quirk. In this episode Ill show how deleting an inline function definition can
lead to similar savings.
The savings this time are less important as they are mostly in the .BSS segment, but
there are also some modest code-size savings, and some interesting lessons. Its worth
confessing up front that this time the problem being solved was not caused by a
compiler quirk it was entirely self inflicted.
Doing this investigation has reminded me that the behavior of linkers is best described
by chaos theory the details of their behavior defy prediction by simple heuristics, and
the results can be changed dramatically by tiny butterflies code changes.
In August of 2016 Chrome switched meta-build systems, from gyp to gn. Both gyp and
gn are systems for creating ninja files and these are the files that define how Chrome is
built. Changing from gyp to gn was a huge project because of the thousands of
assumptions that were embedded in Chromes many .gyp files, but the change was
necessary gyp was showing its age.
Part of my contribution was to help investigate binary size regressions and one
technique I used was to export symbol lists and see which ones appeared in gn builds
but not gyp builds. Here are the six largest globals in chrome.dll from a gyp build near
the transition:
gyp:
122784 kBrotliDictionary
65536 jpeg_nbits_table
54904 propsVectorsTrie_index
47152 device::UsbIds::vendors_
44815 kNetworkingPrivate
39640 propsTrie_index
And here are the six largest globals from a similar gn build:
gn:
131072 ff_sin_65536
131072 ff_cos_65536
122784 kBrotliDictionary
65536 jpeg_nbits_table
65536 ff_sin_32768
65536 ff_cos_32768
The ff_sin* and ff_cos* globals (which go from 65536 entries down to 16) are from
ffmpeg, and since they werent in the gyp build they clearly arent supposed to be in
chrome.dll. A bit of investigation using linker_verbose_tracking.py led to this
change which switched some source_set targets (lists of object files to be linked) to
static_library targets, thus telling the linker to be less aggressive about pulling in their
code. This worked, I closed the bug, and got on with my life.
Ideally the linker would notice the ODR violation, but doing so ends up being expensive
you have to look into every object file to see if any of functions are defined in different
ways, and the definition of different is not obvious. There are good reasons that the C+
+ standard does not require diagnostics for ODR violations.
Ideally chrome.dll wouldnt even list Blink as something to be linked with. Another
Chrome developer has since fixed that.
I still feel bad about not noticing that the arrays were in our official builds after I fixed
them the first time. Luckily Im the sort of developer who randomly downloads symbols
for Chromes canary builds and runs analysis tools on them, so I eventually redeemed
myself.
If youre the sort of developer who likes browsing Chromes source then you can see the
(tiny) change for Windows by typing > git show 036e2ce in a Chromium repo. A more
accessible version can be found here.
The net effect of this change on the size of chrome.dlls sections (in-memory size) was:
chrome.dll
.text:
-6656 bytes change
.rdata:
240 bytes change
.data:
-786624 bytes change
.rodata:
-592 bytes change
.reloc:
-872 bytes change
Total change: -794504 bytes
More details of the techniques used can be found here. If you want to poke at some
relevant chrome.dll PDBs then you can use retrievesymbols from UIforETW to grab
them and then run SymbolSort or ShowGlobals on them. Just set
_NT_SYMBOL_PATH to something like
SRV*c:\symbols*https://msdl.microsoft.com/download/symbols and then run one of
these:
> retrievesymbols B6A75B4A5FE4446CAB6AE159B22DD91F 1 chrome.dll.pdb gyp
build (September 24th, 2016)
> retrievesymbols 0D12FEA487E942BB8719672D45464C51 1 chrome.dll.pdb gn
build (October 30th, 2016)
> retrievesymbols C39CCDB899B34A7CBCC25F51E64B1F62 1 chrome.dll.pdb recent
gn build (January 13, 2017)
These werent the PDBs used for the original investigation, but they show the issue.