Changes between Version 1 and Version 2 of AnalyzingBuildPerformance

Oct 7, 2021 12:14:30 PM (9 months ago)



  • AnalyzingBuildPerformance

    v1 v2  
    1818== Building WebKit with tracing enabled ==
    20 1. Clean your build directory (but make sure it still _exists_).
     201. Clean your build directory (but make sure it still ''exists'').
    21212. `ClangBuildAnalyzer --start path/to/WebKitBuild`
    22223. `make debug ARGS='OTHER_CFLAGS=-ftime-trace OTHER_CPLUSPLUSFLAGS=-ftime-trace' `
    4646From this we can see that JSDOMGlobalObject.h is a very expensive header; it contributes about 3.3s of compile time, on average, to every source file which includes it. And it is included 246 times, which given the WebKit unified build system, means it is included by a majority of source files in the WebCore project. For these expensive headers, its often the case that the "expensive" header is expensive due to including other expensive headers, and one approach to make that header less expensive is to forward declare types rather than include their definitions. In cases where inline implementations of methods make forward declaration impossible, those inline definitions can be moved into a `<Type>Inlines.h` file, and the original declarations annotated with `inline`. Source files which contain references to those inline functions must include the `<Type>Inlines.h` file, or the compile will generate a `-Wundefined-inline` error.
     48=== Header Best Practices ===
     50While resolving some expensive headers, a few best practices stood out to reduce compilation times without regressing runtime performance:
     52==== Forward-declare all the things ====
     54Forward-declaring types used by your class's methods allows clients who don't call those methods to not incur the compile-time cost of including those types' headers.
     56C++ class members must be fully defined, so e.g. consider using `UniqueRef<MyClass>`, and forward-declaring `MyClass`, instead of including `MyClass.h`.
     58C++ function parameters and return values do not need to be fully defined, and can be forward-declared. So e.g. if `MyClass` function parameter or return value, consider forward-declaring `MyClass`, instead of including `MyClass.h`.
     60C++ virtual functions are rarely able to be inlined, even if decorated with `inline`, so avoid inline definitions of virtual functions. So e.g. if defining a virtual base class method that returns a `Ref<MyClass>`, put the default implementation inside the class implementation file.
     62==== Avoid class-scoped enums ====
     64When defining a public enumeration for a class, do so at namespace scope rather than inside the class, and always specify an explicit enum size. E.g.:
     69// MyClass.h
     70class MyClass {
     72    enum Options {
     73        Option1,
     74        Option2,
     75        Option3,
     76    };
     84// MyClass.h
     85enum class MyClassOptions : uint8_t {
     86    Option1,
     87    Option2,
     88    Option3,
     90class MyClass {
     96This allows clients to forward declare the enum type, rather than include `MyClass.h`:
     99// YourClass.h
     100enum class MyClassOptions : uint8_t;
     101class YourClass {
     102    void functionWithMyClassOptions(MyClassOptions);
     106==== Add Inlines.h headers ====
     108When explicitly inlining a function definition for performance reasons, and that definition requires including an external header, putting the inline definition in an Inlines.h header file. Annotate the class method declaration with `inline`, which will cause a compiler warning if the Inline.h header is not included by the caller. E.g.:
     113// MyClass.h
     114#include "YourClass.h"
     115class MyClass {
     117    YourClass& yourClassGetFoo() { return YourClass::foo(); }
     124// MyClass.h
     125class MyClass {
     127    inline YourClass& yourClassGetFoo();
     130// MyClassInlines.h
     131inline YourClass& MyClass::yourClassGetFoo() { return YourClass::foo(); }