14 Jul 2010 19:51
David Moore <davemoore <at> chromium.org>
2010-07-14 17:51:47 GMT
2010-07-14 17:51:47 GMT
On linux we have approximately 1200 modules with at least one static initializer (there may be more than one such initializer in each module). The bulk are explained by the inclusion of header files, leaving around 200 that come from using static variables whose values can't be determined at compile time. Somewhere between 50 and 100 are in chromium code proper, with the rest coming from various third party libraries. Usage of these goes against our style guidelines.
Here's the details:
I started investigating this because on ChromeOS with current hardware we spend about 400ms getting to main() of Chrome. This is because about 26MB needs to be paged in. The data all shows that we're pinned I/O wise during this time, and it fits the read speed of about 70MB/s that we see on the hardware we're testing with. I believe that a significant part of this to come from the code and data paging necessary to run the static initializers, although I'm not sure yet just how much. We have a solution at the OS level that will allow this data to be read during boot without slowing down other boot tasks, but even then less data to read is better.
A few uses / patterns explained a significant percentage:
- Including <iostream>
This file has this in it:
// For construction of filebuffers for cout, cin, cerr, clog et. al.
static ios_base::Init __ioinit;
I believe this is to allow people to use buffered I/O within their own static initializers. But any file that includes iostream in any way gets a static initializer. Commenting this out reduced the number of files with at least one to about 600, and the data read to 24.5MB.
- Including any header that contains a use of scoped_ptr_malloc<>
We have 9 uses in header files. This template includes this declaration:
static FreeProc const free_;
When I remove this declaration (and I'm sure break much of chrome) it further reduces the number of files with at least one static initializer to about 225, and the data read to 19.5MB.
- Statically declaring a SkColor variable with the result of SkColorSetRGB() or SkColorSetARGB()
Even though SkColorSetARGB() is declared as inline the compiler still generates a static initializer. If I replace it with a macro it doesn't. That reduces the files with at least one to about 200, with little affect on the amount of data read.
- Using std::string or std::wstring when we should be using char or wchar_t for string constants.
- Using a static class instance of another kind as a variable, when it should instead be contained within a static function with a local static variable
- Using a static scaler but setting its value to the result of a function call that can't be computed at compile time, such as string16.
I've attached the list of these files. This list only has the filenames and includes third party things as well.
Here's what I think we should do:
- Find solutions to the 3 patterns above. Perhaps we're including these things way more aggressively than we need to. Or maybe there's a way to avoid the statics in the first place.
- Fix the remaining things. Most of the changes (at least w/in the chromium source) are straightforward. I can do it, or the people who know the code better can.
- Get better about looking for these things in code reviews and reject any changes that contain code that produces static initializers. I believe webkit already does this.
- Add tools to the perfbots that can track the number of static initializers that we have in the code. I haven't looked at the Windows or Mac side of this, but it's relatively easy to find them in the ELF format, using readelf and looking for the .ctors section.
Chromium Developers mailing list: chromium-dev <at> chromium.org
View archives, change email options, or unsubscribe: