Page 1 of 1
fontconfig is slow
Posted: Mon Oct 10, 2022 3:33 pm
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?
Re: fontconfig is slow
Posted: Mon Oct 10, 2022 5:51 pm
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.
Re: fontconfig is slow
Posted: Mon Oct 10, 2022 6:30 pm
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.
Re: fontconfig is slow
Posted: Mon Oct 10, 2022 9:48 pm
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.
Re: fontconfig is slow
Posted: Mon Oct 10, 2022 11:28 pm
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.
Re: fontconfig is slow
Posted: Tue Oct 11, 2022 4:27 am
by devc1
That's what I was going to say !
Implement a VFS that contains these files loaded in memory.
Re: fontconfig is slow
Posted: Tue Oct 11, 2022 5:03 am
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.
Re: fontconfig is slow
Posted: Tue Oct 11, 2022 5:40 am
by devc1
Okay
Re: fontconfig is slow
Posted: Tue Oct 11, 2022 11:01 am
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.
Re: fontconfig is slow
Posted: Fri Oct 14, 2022 6:57 pm
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.
Re: fontconfig is slow
Posted: Mon Oct 17, 2022 7:59 pm
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.