fontconfig is slow

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
AndrewAPrice
Member
Member
Posts: 2300
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

fontconfig is slow

Post by AndrewAPrice »

(Mostly a rant, unless others have encountered and solved this problem.)

I ported fontconfig to my OS as a dependency of Skia, and it is slow.

Specifically, the operation in Skia's SkFontConfigInterfaceDirect::matchFamilyName calls FcConfigReference, which iterates over the 22 .ttf files I have in my font directory. This takes minutes! I tried using Skia's custom font directory instead of FontConfig, but it also takes minutes, as it opens each font with TrueType and reads the faces out.

Minutes seems ridiculously long to iterate over 22 fonts. Especially if it happens at the launch of each of program. I suppose this is the purpose of the fc-cache tool, and I should create the cache as part of my build process and bundle it with my OS image?
My OS is Perception.
devc1
Member
Member
Posts: 439
Joined: Fri Feb 11, 2022 4:55 am
Location: behind the keyboard

Re: fontconfig is slow

Post by devc1 »

You can just cache these files into memory, or make a faster disk driver. A typical hard drive can read these 22 fonts in less than a second.
User avatar
AndrewAPrice
Member
Member
Posts: 2300
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: fontconfig is slow

Post by AndrewAPrice »

Fontconfig just provides enumeration and matching of fonts?

This might be better provided by a service that can be queried via an RPC than a library and every program has to load and process data from disk.
My OS is Perception.
User avatar
AndrewAPrice
Member
Member
Posts: 2300
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: fontconfig is slow

Post by AndrewAPrice »

devc1 wrote:You can just cache these files into memory, or make a faster disk driver. A typical hard drive can read these 22 fonts in less than a second.
I noticed it does a lot of small reads, such as 30 bytes at a time. I'm not doing caching at the libc level so each one of these involves 2 RPCs and disk IO.
My OS is Perception.
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: fontconfig is slow

Post by iansjack »

AndrewAPrice wrote:
devc1 wrote:I'm not doing caching at the libc level so each one of these involves 2 RPCs and disk IO.
Well, there’s your solution. You need to implement buffered I/O.
devc1
Member
Member
Posts: 439
Joined: Fri Feb 11, 2022 4:55 am
Location: behind the keyboard

Re: fontconfig is slow

Post by devc1 »

That's what I was going to say !
Implement a VFS that contains these files loaded in memory.
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: fontconfig is slow

Post by iansjack »

It’s not the file system. It’s the library call that implements the read function. It should implement a buffer so that several I/O operations require only a single system call. Not only does this save system calls but it also reduces the number of (very slow) disk read operations.
devc1
Member
Member
Posts: 439
Joined: Fri Feb 11, 2022 4:55 am
Location: behind the keyboard

Re: fontconfig is slow

Post by devc1 »

Okay :)
User avatar
AndrewAPrice
Member
Member
Posts: 2300
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: fontconfig is slow

Post by AndrewAPrice »

I found an issue: musl does buffer file io, however musl's fseek clears the buffer.

There's a lot of back and forth jumping as fontconfig/freetype try to parse the fonts. Reading 16 bytes from position 172, seeking to 270568 to read 4 bytes, then seeking back to position 188. Or, we'll read 32 bytes from 291146, then seek 19 bytes ahead from 291178 to 291197. Another time, we seek to 444, read 2 bytes, see we seek to 454, read 2 bytes, seek to 462, read 6 bytes, seek to 468, read 6 bytes. etc. Approx 2446 times we try to read 2 bytes from position 270660.

According to https://freetype.org/freetype2/docs/des ... ign-4.html:
As an example, the default implementation of streams is located in the file src/base/ftsystem.c and uses the ANSI functions fopen, fseek, and fread. However, the Unix build of FreeType 2 provides an alternative implementation that uses memory-mapped files, when available on the host platform, resulting in a significant access speed-up.
Perhaps I need to add memory mapped file support.
My OS is Perception.
User avatar
AndrewAPrice
Member
Member
Posts: 2300
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: fontconfig is slow

Post by AndrewAPrice »

I implemented memory mapped IO, and it sped fontconfig up from minutes to seconds. I see that fontconfig is looking every which direction for a cache file, and that would speed up each launch if it could just open a single file rather than recomputing on each process launch. The fastest thing would be to try to avoid any file read at all.

Skia calls fontconfig to do one thing, which is to find a font that matches a family and style. This is something we could do via an RPC to a service, and save having to create an instance of fontconfig for each process. I'm building a Font Manager that loads fontconfig and exposes a MatchFont RPC. To speed things up even further, my Font Manager could cache my default fonts in memory to avoid any file IO.
My OS is Perception.
User avatar
AndrewAPrice
Member
Member
Posts: 2300
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: fontconfig is slow

Post by AndrewAPrice »

I implemented my Font Manager and substituted Skia's calls to fontconfig to be RPCs. Now the redundant work doesn't have to happen for each process.

Each process still needs to load the matched font, but so far this is much fast. I have shared memory (I added read-only support for MMIO), so a step further would be to cache common UI fonts in the Font Manager, and then it can return either a file path or a memory buffer.
My OS is Perception.
Post Reply