commit | e522d38d629d7522f0589e754886ed2b82232d9e | [log] [tgz] |
---|---|---|
author | Valentin Hăloiu <valentin.haloiu@gmail.com> | Wed May 24 20:53:44 2023 +0100 |
committer | GitHub <noreply@github.com> | Wed May 24 12:53:44 2023 -0700 |
tree | 54e4d7877f51570c03fe4babf4a60baa5688b5f3 | |
parent | aee1094b10465e32972932e23b6799c3f8de244f [diff] |
Dynamically link against system fontconfig (#701) Statically linking the fontconfig library into the flutter app can cause (runtime) performance issues on systems where the statically linked fontconfig is using a different [on-disk cache format version](https://gitlab.freedesktop.org/fontconfig/fontconfig/-/blob/c2666a6d9a6ed18b1bfcef8176e25f62993e24db/fontconfig/fontconfig.h#L60-70) from the system fontconfig version. This is particularly relevant on systems with a large number of fonts installed: https://github.com/flutter/flutter/issues/118911. This pull-request fixes that by replacing the statically linked fontconfig version with dynamic linking to the system version. For what it's worth, by default Skia is also [dynamically linking against system fontconfig](https://github.com/google/skia/blob/398b9ac94aa3f49e0fdab319a27584c2a2e3e63e/third_party/BUILD.gn#L10). **Warning**: This requires a similar change to the Flutter engine (https://github.com/flutter/engine/pull/40725). ### Underlying root issue On a typical Linux desktop distribution[^1], the package manager automatically updates the *system* fontconfig cache (e.g.: `/var/cache/fontconfig`) when *system* fonts are installed. This means that applications using a version of fontconfig with *the same on-disk cache format as the system fontconfig* should be able to use the system cache (and therefore have reasonably fast font discovery). However, when the application and system fontconfig versions do not match, the app is unable to use the system font cache so it has to re-index all the system fonts (which is a significantly slower operation). In addition to that, in an attempt to speed-up subsequent launches of the app, the fontconfig library persists the system font cache to disk on application startup. Since user-space apps typically do *not* have write access to the *system* font cache directory (e.g.: `/var/cache/fontconfig`), the fontconfig library ends up writing the cache to the *user* fontconfig cache (e.g.: `~/.cache/fontconfig`) which ends up slowing the application startup even futher (due to the extra IO). This part is a bit unclear as to *why* it happens, but it turns out fontconfig does not attempt to read the *user* cache on the next app startup. So the whole process starts over again on every app launch: *system* font cache not found => fonts re-indexed => font cache written to *user* cache (which is never to be read again). ### Benchmarks > **Note** > > These tests were performed on an ArchLinux system with approximately 6000 system fonts installed ([ttf-google-fonts-git](https://aur.archlinux.org/packages/ttf-google-fonts-git)) using version `2.14.2` of fontconfig (`FC_CACHE_VERSION: 8`). The following graph shows the startup times (time to first frame as reported by `flutter run --profile`) for ten consecutive runs using statically linked fontconfig versus dynamically linked fontconfig. The average startup time for statically linked fontconfig was 2186 ms versus 368 ms for dynamically linked. ![chart](https://user-images.githubusercontent.com/433598/228365920-1f90eddb-683e-46d3-9aec-4df22fa222db.png) ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read the [Flutter Style Guide] _recently_, and have followed its advice. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [test-exempt]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat [^1]: This has only been tested on ArchLinux but I would expect other Linux distributions to work in a similar way.
Build environment for the Flutter engine
This repository is used by the flutter/engine repository. For instructions on how to use it, see that repository's CONTRIBUTING.md file.
To update your checkout to use the latest buildroot, run gclient sync
.
To submit patches to this buildroot repository, create a branch, push to that branch, then submit a PR on GitHub for that branch.
To point the engine to a new version of buildroot after your patch is merged, update the buildroot hash in the engine's DEPS file.