servo / font-kit

A cross-platform font loading library written in Rust
Apache License 2.0
693 stars 104 forks source link

`SystemSource::new()` very slow on Linux, asks fontconfig to scan all system fonts #148

Open nyanpasu64 opened 4 years ago

nyanpasu64 commented 4 years ago

I recently reported https://github.com/hecrj/iced/issues/351:

When I launch any of the iced example apps, it hangs on a blank window for around 31 seconds while loading fonts. The slowness occurs in fontconfig C functions, called by the the font-kit crate. Incidentally, reloading fc-cache is also a fairly slow process taking the same "order of magnitude" time.

During the hang, the terminal prints out all sorts of funny messages: https://youtu.be/-WZaFURNJYs

(gdb) bt
#0  0x000055555600bc7c in FT_Stream_ReadFields ()
#1  0x0000555556029b9c in pcf_load_font ()
#2  0x000055555602b193 in PCF_Face_Init ()
#3  0x000055555600cd14 in open_face ()
#4  0x000055555600db15 in FT_Open_Face ()
#5  0x000055555600e086 in FT_New_Face ()
#6  0x0000555555fcb13b in FcFreeTypeQuery ()
#7  0x0000555555fc8646 in FcFileScanFontConfig ()
#8  0x0000555555fc87a1 in FcFileScanConfig ()
#9  0x0000555555fc8a56 in FcDirScanConfig ()
#10 0x0000555555fc8bb8 in FcDirCacheScan ()
#11 0x0000555555fc8da1 in FcDirCacheRead ()
#12 0x0000555555fc0092 in FcConfigAddDirList ()
#13 0x0000555555fc0162 in FcConfigBuildFonts ()
#14 0x0000555555fcdcec in FcInitLoadOwnConfigAndFonts ()
#15 0x0000555555fcdd17 in FcInitLoadConfigAndFonts ()
#16 0x0000555555f885ba in font_kit::sources::fontconfig::fc::Config::new ()
    at /home/nyanpasu64/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.6.0/src/sources/fontconfig.rs:300
#17 0x0000555555f8ced9 in font_kit::sources::fontconfig::FontconfigSource::new ()
    at /home/nyanpasu64/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.6.0/src/sources/fontconfig.rs:40
#18 0x0000555555b4e2fa in iced_wgpu::text::font::Source::new () at wgpu/src/text/font.rs:12
#19 0x0000555555b40321 in iced_wgpu::text::Pipeline::new (device=0x7fffffff9b08, format=wgpu_types::TextureFormat::Bgra8UnormSrgb, 
    default_font=...) at wgpu/src/text.rs:31
#20 0x0000555555af0f85 in iced_wgpu::renderer::Renderer::new (device=0x7fffffff9b08, settings=...) at wgpu/src/renderer.rs:64
#21 0x0000555555b62d4a in <iced_wgpu::window::backend::Backend as iced_native::window::backend::Backend>::new (settings=...)
    at wgpu/src/window/backend.rs:46
#22 0x00005555556bf5c8 in iced_winit::application::Application::run (settings=..., backend_settings=...)
    at /home/nyanpasu64/code/iced/winit/src/application.rs:180
#23 0x00005555556fd077 in iced::application::Application::run (settings=...) at /home/nyanpasu64/code/iced/src/application.rs:201
#24 0x00005555556f5533 in clock::main () at examples/clock/src/main.rs:8

I think this is font-kit's fault. iced-wgpu calls font_kit::source::SystemSource::new():

https://github.com/hecrj/iced/blob/33448508a524db6447b380cc236be6f0d5ca8a86/wgpu/src/text/font.rs#L12

and everything from then on is font-kit's responsibility.

Interestingly, sudo fc-cache -f only takes 6 seconds and doesn't print any funny messages. And launching kate in gdb, the call to FcConfig * FcInitLoadConfigAndFonts(void) only takes a few seconds and prints no errors to the terminal.

This issue occurs with both font-kit 0.6.0 and 0.7.0.

wlottoculus commented 4 years ago

I also hit this while trying out iced. I poked a little deeper, and the issue isn't with font-kit itself, but with servo-fontconfig-sys. Servo-fontconfig-sys is a snapshot of fontconfig 2.11.1 and gets confused by fontconfig 2.13's config files, which causes FcInitLoadConfigAndFonts to be quite slow. I hacked a servo-fontconfig-sys build out of fontconfig 2.13.92's sources and the warning spew and slowness went away.

jdm commented 4 years ago

I filed https://github.com/servo/libfontconfig/issues/57 to track that issue. Thanks for pointing that out!

wlottoculus commented 4 years ago

Additional detail: if you have a newer fontconfig installed system-wide, servo-fontconfig-sys will use it instead of the embedded fontconfig 2.11.1. Too bad nothing tells you that installing it would be a good idea.