[read-fonts] Add per-table feature flags
This dramatically reduces compile times for read-fonts in cases where only a few tables are needed. Examples of cases where this applies include fontdb and fontique which only need to read high-level metadata and don't need to access details like glyph outlines, shaping, or hinting data.
Notes:
- This was also surprisingly easy to do (the tables' implementation were mostly already independent of each other.
- It would be relatively easy to further reduce the dependencies between modules: many of the dependencies are "trivial" dependencies that only need one or two types from the module they depend on. We could pull these types out into a shared module to remove the dependency
- I have added a CI job using "cargo hack" that runs
cargo checkwith each feature flag to ensure that they all compile independently of each other.
Any reason not to include gdef in layout?
Any reason not to include
gdefinlayout?
It's perhaps not obvious from the names, but "layout" is actually support code tables that deal with layout rather than the group of tables that deal with layout (the feature names match file/module names the read-fonts/tables directory).
Perhaps we should make that clearer by suffixing the names with _support or _base or similar. And consider adding actual meta-features for table groups.
It's perhaps not obvious from the names, but "layout" is actually support code tables that deal with layout rather than the group of tables that deal with layout (the feature names match file/module names the
read-fonts/tablesdirectory).
I suspected that. Thanks for clarifying. I think it's fine.
I feel like this isn’t going to be much of a win in practice. Doing anything useful with a font is going to require at least one of skrifa or harfrust, both of which need all of the expensive-to-compile tables.
I feel like this isn’t going to be much of a win in practice. Doing anything useful with a font is going to require at least one of skrifa or harfrust, both of which need all of the expensive-to-compile tables.
There are alternatives to these, so it could be that you combine a subset of read-fonts with ttf_parser or the C FreeType/HarfBuzz. This may be important for adoption of Fontique (although I suspect HarfRust is going to sway people to depend on read-fonts anyway). It could also be useful for things like WOFF encoding that only need to read the header + 3 or 4 tables (the rest being passed through as byte slices).
Something else I'm looking at is the possibility of splitting things up into crates. The benefit there would that it would allow tables to compile in parallel (it's possible that it also reduces overall type checking time as I believe that rustc has superlinear scaling with respect to crate size).
See (for example) the waterfall graph for the fontations port of resvg. It's compile times are completely dominated by the single-core build time of read-fonts (and to a lesser extent: skrifa, harfrust and read-fonts proc_macro deps):
Seems suspicious that we enable the traversal feature by default: https://github.com/googlefonts/fontations/blob/237e69658be195a73a27c0dab576fee6fddddcde/skrifa/Cargo.toml#L19
Does disabling that have any measurable impact on compile times?
Seems suspicious that we enable the traversal feature by default:
https://github.com/googlefonts/fontations/blob/237e69658be195a73a27c0dab576fee6fddddcde/skrifa/Cargo.toml#L19
Does disabling that have any measurable impact on compile times?
I'm seeing a bit of variance (cargo clean && cargo build -rp skrifa --timings), but that seems to shave off about 2 (out of 8) seconds on average. Which is not bad at all for such a small fix.
With traversal:
Without traversal:
Nice! I suggest we start by removing that as a default feature and then looking for ways to improve codegen before we start cutting up the code with features or crate splitting.
Examples of cases where this applies include fontdb and fontique which only need to read high-level metadata and don't need to access details like glyph outlines, shaping, or hinting data.
I'm curious, are there users that only need these? - the consumers that come to mind for me would also typically need at least one of shaping, subsetting, and access to outlines.
looking for ways to improve codegen before we start cutting up the code with features or crate splitting.
vigorous +1, lets push on this first. Reminds me, I'm curious if anyone observes a measurable improvement from https://github.com/googlefonts/fontations/pull/1661? - wasn't a clear win when I tried it.