MLFont: Machine Learning-Driven Font Subsetting and Range-Compact Unicode-Range Slicing for Low-Latency Web Typography
Abstract
CSS3 @font-face rules with unicode-range descriptors partition web fonts into downloadable slices. While Latin fonts need ~20 KB in WOFF2, Pan-European (LGC) and East Asian (CJK) fonts contain 2,297-30,759 codepoints (158 KB-5.9 MB in WOFF2), where heuristic partitioning causes unused-glyph downloads, high HTTP RTT, CSS bloat, or missing-glyph fallbacks. We present MLFont, a machine learning and optimization framework that learns font slicing strategies from corpora via three stages: (1) a Zipfian High-Frequency Tier (most) isolating top-frequency codepoints; (2) a Latent Co-Occurrence Topic Tier using Online Variational Bayes LDA (Online LDA) or a Deep Neural Network Topic Model (DNNTM) with Shannon Entropy Difference Loss and Sinkhorn-Knopp normalization; and (3) a Memetic Range-Compact Genetic Algorithm (GA) with Potts-Viterbi dynamic programming and island bridging that minimizes topic discrepancy and CSS fragmentation. Across five Google Noto fonts (LGC, KR, JP, TC, SC), MLFont cuts 3G per-glyph latency by 56.7%-75.3% over single-file delivery and 46.1%-66.3% over equal-bin baselines on CJK with 100% coverage, reduces CSS intervals by 17.9%-41.7%, and achieves 1.56x-6.09x cold-cache speedups (65.4%-84.9% CJK and 44.7% LGC bandwidth savings) across 20 websites in simulator and Headless Chrome benchmarks (45/45 exact slice-set parity). Code: https://github.com/wq2012/mlfont Models: https://huggingface.co/collections/wq2012/mlfont
Figures & tables
| Font Family | Strategy | Slices | Missing (Eval / Font) | CSS Ranges | Mean (ms) | P95 (ms) | Upfront Util | Session Util |
|---|---|---|---|---|---|---|---|---|
| Noto Sans LGC | single_slice | 1 | 0 / 0 | 123 | 15.22 | 143.10 | 2.83% | 8.66% |
| ( cps) | equal_bin_20 | 20 | 0 / 0 | 140 | 9.44 | 43.41 | 20.92% | 23.17% |
| random_slice_20 | 20 | 0 / 0 | 2,180 | 27.11 | 256.54 | 2.91% | 8.66% | |
| language_slice ( .nam ) | 8 | 6 / 300 | 92 | 10.62 | 66.28 | 18.85% | 15.08% | |
| MLFont Online LDA (20 slices) | 20 | 0 / 0 | 537 | 7.11 | 40.95 | 19.16% | 31.26% | |
| MLFont DNNTM (20 slices) | 20 | 0 / 0 | 549 | 6.59 | 31.88 | 31.79% | 32.56% |
| Normalization ( ) | Ranges | 2G (ms) | 3G (ms) | Sess Util |
|---|---|---|---|---|
| row_sum (Row ) | 421 | 25.15 | 7.12 | 31.15% |
| topic_sum (Col ) | 549 | 25.17 | 7.12 | 31.26% |
| global_max ( ) | 537 | 25.15 | 7.11 | 31.26% |
| spectral_norm ( ) | 537 | 25.15 | 7.11 | 31.26% |
| sinkhorn (Bi-stochastic) | 542 | 24.65 | 6.98 | 31.77% |
| DNNTM Loss Objective ( ) | Ranges | 2G (ms) | 3G (ms) | Sess Util |
| Strategy ( Noto Sans SC ) | (ms) | (ms) | (ms) | Sess Util ( ) |
|---|---|---|---|---|
| single_slice | 418.33 | 152.09 | 63.47 | 5.55% |
| equal_bin_102 | 296.91 | 116.97 | 45.26 | 7.63% |
| most_1000_500_equal_bin_100 | 130.06 | 73.57 | 29.38 | 7.82% |
| MLFont Online LDA ( ) | 81.79 | 36.68 | 15.93 | 16.90% |
| MLFont DNNTM ( ) | 78.20 | 35.89 | 15.71 | 16.57% |
| MLFont Range-Compact GA ( ) | 89.11 | 40.78 | 17.67 | 14.64% |
Appendix figures & tables5 assets
Supplementary material from the paper’s appendix.
Appendix
| System Component | Open-Source Implementation ( mlfont ) |
|---|---|
| Data & Corpus Processing | Pure Python 3.10+ with NumPy & SciPy sparse co-occurrence matrices over public Wikimedia/Wikipedia corpora ( wikimedia/wikipedia ) |
| Tier-1 Frequency Isolation | Deterministic Zipfian document-frequency partitioner ( FrequencySolver , most_1..M ) |
| Online LDA Solver | OnlineLdaLearner with two-tier Hungarian contiguous-bin Bayes alignment + Sinkhorn-Knopp bi-stochastic scaling |
| Neural Topic Model (DNNTM) | PyTorch DnnTmLearner unifying non-negative Shannon Entropy Difference Losses with Nonnegative Sparse Autoencoder reconstruction |
| Combinatorial Optimizer | Memetic RangeCompactGeneticLearner ( PowerDecay + Lagrangian 1D Potts-Viterbi DP + Sparse-Tail Island Bridging) |
| Physical Font Subsetting | fontTools.subset ( woff2 Brotli compression) + CSS3 @font-face unicode-range stylesheet generator |
| Hugging Face Repository | Font Binary | Languages / Scripts | Codepoints | Tier-1 ( most ) | Topics ( ) | Total Slices | Physical WOFF2 (CSS) |
|---|---|---|---|---|---|---|---|
| wq2012/mlfont-notosans-lgc | NotoSans-Regular.ttf | en, de, fr, pl, ru, el | ( ) | KB ( KB CSS) | |||
| wq2012/mlfont-notosanskr | NotoSansKR-Regular.otf | Korean ( ko , Hangul/Hanja) | ( ) | MB ( KB CSS) | |||
| wq2012/mlfont-notosansjp | NotoSansJP-Regular.otf | Japanese ( ja , Kanji/Kana) | ( ) | MB ( KB CSS) | |||
| wq2012/mlfont-notosanstc | NotoSansTC-Regular.otf | Trad. Chinese ( zh-Hant ) | ( ) | MB ( KB CSS) | |||
| wq2012/mlfont-notosanssc | NotoSansSC-Regular.otf | Simp. Chinese ( zh-Hans ) | ( ) | MB ( KB CSS) |
| Font Family | Strategy | CSS Ranges | 2G Mean | 2G P95 | 3G Mean | 3G P95 | DSL Mean | DSL P95 | ADSL2+ Mean |
|---|---|---|---|---|---|---|---|---|---|
| Noto Sans LGC | single_slice | 123 | 60.26 | 566.45 | 15.22 | 143.10 | 3.00 | 28.17 | 0.37 |
| ( cps) | equal_bin_20 | 140 | 33.37 | 153.43 | 9.44 | 43.41 | 1.56 | 7.17 | 0.65 |
| random_slice_20 | 2,180 | 95.82 | 906.75 | 27.11 | 256.54 | 4.48 | 42.35 | 1.87 | |
| language_slice ( unass.) | 92 | 40.17 | 258.54 | 10.62 | 66.28 | 1.95 | 12.76 | 0.45 | |
| MLFont Online LDA (20) | 537 | 25.15 | 144.76 | 7.11 | 40.95 | 1.17 | 6.76 | 0.49 | |
| MLFont DNNTM (20) | 549 | 23.29 | 112.70 | 6.59 | 31.88 | 1.09 | 5.26 | 0.45 |
| Font Family | Slices | Avg WOFF2 B/glyph | GIN-3g ( B) | GIN-3g (Physical WOFF2) | DSL ( B) | DSL (Physical WOFF2) |
|---|---|---|---|---|---|---|
| Noto Sans LGC | 20 | B | 7.06 / 40.06 | 6.71 / 39.49 | 1.17 / 6.64 | 1.10 / 6.47 |
| Noto Sans KR | 52 | B | 21.06 / 93.00 | 25.52 / 116.06 | 3.91 / 17.27 | 4.80 / 22.05 |
| Noto Sans JP | 62 | B | 11.37 / 59.70 | 16.29 / 87.35 | 2.05 / 10.79 | 3.04 / 16.37 |
| Noto Sans TC | 82 | B | 15.07 / 71.62 | 20.75 / 99.90 | 2.71 / 12.79 | 3.85 / 18.42 |
| Noto Sans SC | 102 | B | 17.67 / 94.33 | 23.96 / 126.04 | 3.23 / 17.32 | 4.49 / 23.67 |