[webkit-dev] Growing tired of long build times? Check out this awesome new way to speed up your build... soon (HINT: It's not buying a new computer)
Michael Catanzaro
mcatanzaro at igalia.com
Tue Aug 29 12:21:56 PDT 2017
I'd like to propose a variation on Keith's proposal. I think we should
manually determine which files should be built together, rather than
writing CMake code to do that automatically.
Let's consider an example of what use of the FILENAME namespace, as
Keith proposes, might look like. I opened a couple big files in WebCore
and settled on this representative code snippet from
HTMLMediaElement.cpp:
> #if ENABLE(MEDIA_SESSION)
> typedef HashMap<uint64_t, HTMLMediaElement*> IDToElementMap;
>
> static IDToElementMap& elementIDsToElements()
> {
> static NeverDestroyed<IDToElementMap> map;
> return map;
> }
>
> HTMLMediaElement* HTMLMediaElement::elementWithID(uint64_t id)
> {
> if (id == HTMLMediaElementInvalidID)
> return nullptr;
>
> return elementIDsToElements().get(id);
> }
>
> static uint64_t nextElementID()
> {
> static uint64_t elementID = 0;
> return ++elementID;
> }
> #endif
In Keith's proposed scheme, the static functions need to go into the
FILENAME namespace. The typedef probably should as well, since we'd
want to ensure it doesn't clash with other hypothetical typedefs in
other files. (The chances of another file having a typedef of the name
IDToElementMap are probably rather low, but that's also true for the
function names as well.) And *the uses of the static functions from
outside the namespace will now need to be qualified as well* (thanks to
Alicia for pointing that out; seems obvious, but I'd missed it). So the
result, if we don't reorder anything, would have to look like this:
> #if ENABLE(MEDIA_SESSION)
> namespace FILENAME {
> typedef HashMap<uint64_t, HTMLMediaElement*> IDToElementMap;
>
> static IDToElementMap& elementIDsToElements()
> {
> static NeverDestroyed<IDToElementMap> map;
> return map;
> }
> } // namespace FILENAME
>
> HTMLMediaElement* HTMLMediaElement::elementWithID(uint64_t id)
> {
> if (id == HTMLMediaElementInvalidID)
> return nullptr;
>
> return FILENAME::elementIDsToElements().get(id);
> }
> namespace FILENAME {
> static uint64_t nextElementID()
> {
> static uint64_t elementID = 0;
> return ++elementID;
> }
>
> } // namespace FILENAME
>
> #endif
We could reorder functions and add more forward declarations to reduce
the number of extra namespace declarations that we'll need. But there's
nothing we can do to eliminate the mess caused by needing to use the
extra FILENAME:: scope when using the static variables and functions
outside the namespace:
return FILENAME::elementIDsToElements().get(id);
If it's going to improve clean build times by 80%, then we should
probably put up the this messiness to get the faster build... but
surely nobody is going to be very fond of making our code messier.
(Tangent: I expect this might discourage future use of file-static
functions and encourage the use of private class member functions.
Ryusuke and Darin have already shown why that's a bad idea.)
We would be better off *not* attempting to avoid naming clashes
automatically, i.e. not using the FILENAME namespace. If we give up on
automatically bundling sources together, and instead group them
together manually or semi-manually in the build system so that adding a
new file does not unexpectedly result in changing which other files get
bundled together, then we can get the benefits of unified builds
without needing to make significant modifications to our source code.
We would only need to rename static variables and functions in the rare
cases that there are actual name collisions with other files in the
same bundle. I expect such cases will be quite rare. The cost is that
we would have to manually manage which files get bundled together in
CMake, rather than having this be determined automatically as under
Keith's plan.
For example, currently in Source/WebCore/CMakeLists.txt we have:
> set(WebCore_SOURCES
> Modules/airplay/WebKitPlaybackTargetAvailabilityEvent.cpp
>
> Modules/beacon/NavigatorBeacon.cpp
>
> Modules/cache/Cache.cpp
> Modules/cache/CacheStorage.cpp
> Modules/cache/CacheStorageConnection.cpp
> Modules/cache/DOMCache.cpp
> Modules/cache/DOMWindowCaches.cpp
> Modules/cache/WorkerCacheStorageConnection.cpp
> Modules/cache/WorkerGlobalScopeCaches.cpp
>
> # ...
> )
We could instead write something like this:
> ADD_SOURCES_BUNDLE(WebCore_SOURCES
> Modules/airplay/WebKitPlaybackTargetAvailabilityEvent.cpp
> Modules/beacon/NavigatorBeacon.cpp
> )
>
> ADD_SOURCES_BUNDLE(WebCore_SOURCES
> Modules/cache/Cache.cpp
> Modules/cache/CacheStorage.cpp
> Modules/cache/CacheStorageConnection.cpp
> Modules/cache/DOMCache.cpp
> Modules/cache/DOMWindowCaches.cpp
> Modules/cache/WorkerCacheStorageConnection.cpp
> Modules/cache/WorkerGlobalScopeCaches.cpp
> )
We'd have to figure out how to implement ADD_SOURCES_BUNDLE.
I expect manually determining which files to bundle together will be
less optimal that automatically determining which files should be built
together, since Keith has already figured out the ideal bundle size and
our bundles are surely going to deviate from that, especially after
files get added or removed. But making the bundles deterministic should
eliminate the need for the FILENAME namespace, and we should still get
a big speedup over where we are now, so that should be worth it. I'd
much rather have additional complexity in our CMake build system than
in our C++ sources. And it should be straightforward to remove this
extra complexity from our build system when we decide to switch to C++
modules in the future.
Michael
More information about the webkit-dev
mailing list