- 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.
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
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.
I've spot checked the remaining 200 and they appear to fall into a few camps:
- 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.
Dave
--
Chromium OS Developers mailing list: chromiu...@chromium.org
View archives, change email options, or unsubscribe:
http://trac.webkit.org/browser/trunk/JavaScriptCore/wtf/StaticConstructors.h
is all I could find. It provides a macro that is used in place of
statics that has the effect of a static without an initializer being
involved.
24 // We need to avoid having static constructors. We achieve this
25 // with two separate methods for GCC and MSVC. Both methods prevent
the static
26 // initializers from being registered and called on program
startup. On GCC, we
27 // declare the global objects with a different type that can be POD default
28 // initialized by the linker/loader. On MSVC we use a special
compiler feature
29 // to have the CRT ignore our static initializers. The constructors
will never
30 // be called and the objects will be left uninitialized.
31 //
32 // With both of these approaches, we must define and explicitly call an init
33 // routine that uses placement new to create the objects and overwrite the
34 // uninitialized placeholders.
35 //
36 // This is not completely portable, but is what we have for now without
37 // changing how a lot of code accesses these global objects.
There's also a step in the build (at least on mac) that checks for
static initializers and errors out if any are present.
Adam
I could be wrong, but I think it just runs this script:
http://trac.webkit.org/browser/trunk/WebKitTools/Scripts/check-for-global-initializers
Adam
Adding const didn't change anything. I've reduced it to all code in one file that looks like this:typedef unsigned int SkColor;typedef unsigned char uint8_t;static const inline SkColor SkColorSetARGB(uint8_t a, uint8_t r, uint8_t g, uint8_t b) {return (a << 24) | (r << 16) | (g << 8) | (b << 0);}
static inline SkColor SkColorSetARGB(uint8_t a, uint8_t r, uint8_t g, uint8_t b) const {
return (a << 24) | (r << 16) | (g << 8) | (b << 0);
To make the function const, you need to declare as:static inline SkColor SkColorSetARGB(uint8_t a, uint8_t r, uint8_t g, uint8_t b) const
gcc supports the function attributes const and pure (const being pure
and additionally does not access global objects). If it would help to
reduce the amount of static initializers, we could add a macro
CONST_FUNCTION or similar that would evaluate to
__attribute__((const)) if compiled with gcc and to nothing otherwise.
>
> --
> Chromium Developers mailing list: chromi...@chromium.org
> View archives, change email options, or unsubscribe:
> http://groups.google.com/a/chromium.org/group/chromium-dev
>
gcc supports the function attributes const and pure (const being pure
and additionally does not access global objects). If it would help to
reduce the amount of static initializers, we could add a macro
CONST_FUNCTION or similar that would evaluate to
__attribute__((const)) if compiled with gcc and to nothing otherwise.
>
> --
> Chromium Developers mailing list: chromi...@chromium.org
> View archives, change email options, or unsubscribe:
> http://groups.google.com/a/chromium.org/group/chromium-dev
>
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.
~scoped_ptr_malloc() { | |
- free_(ptr_); | |
|
I've spot checked the remaining 200 and they appear to fall into a few camps:
- 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.
Dave
My experience is scoped_ptr_malloc<> is a bit disappointing to use. Every time I have needed it, I just have a plain old static function I want to bind it to, yet I need to code up a functor class just to call it. It's even more disappointing to find this class has a knock-on cost on app startup time. Perhaps a version for use with a plain function would help ...