6

luatex loads a lot of otf fonts at every luaLaTeX run with my custom class (Minion Pro, Myriad Pro, Minion Math, Latin Modern Mono, Latin Modern Math, XITS). This is an extract taken from my custom class:

\RequirePackage{fontspec}


\RequirePackage[math-style = TeX]{unicode-math}
\setmathfont[version=bold]{MinionMath-Bold}
\setmathfont[Extension = .otf,
             Scale = 1,
             Script = Math,
             SizeFeatures = {%
                              {%
                                Size = -6, 
                                Font = MinionMath-Tiny,
                                Style = MathScriptScript},
                              {%
                                Size = 6-8.4, 
                                Font = MinionMath-Capt,
                                Style = MathScript},
                              {%
                                Size = 8.4-,
                                Font = MinionMath-Regular},
                            }
            ]{MinionMath-Regular}
\setmathfont[range={\mathfrak}]{latinmodern-math.otf}
\setmathfont[range={\mathcal}]{latinmodern-math.otf}
\setmathfont[range={\mathscr}]{xits-math.otf}
\setmathfont[range={}]{MinionMath-Regular.otf}

\usepackage{unicode-minionmath}

\setmainfont{MinionPro}[
  Extension = .otf,
  UprightFont = *-Regular,
  BoldFont = *-Bold,
  ItalicFont = *-It,
  BoldItalicFont = *-BoldIt,
  ]

\setsansfont{MyriadPro}[
  Extension = .otf,
  UprightFont = *-Regular,
  BoldFont = *-Semibold,
  ItalicFont = *-It,
  BoldItalicFont = *-SemiboldIt,
  ]

\setmonofont{LatinModernMono}

On my system (linux, SSD, core i3), each run takes at least 10 seconds. If I understand correctly, much of the time is spent reading byte compiled lua tables storing all the information needed to take care of an otf font.

Having a look at those tables (stored in ~/.texlive2016/texmf-var/luatex-cache/generic/fonts/otl/), it seems to me that most of the elements (unicode characters) there are nearly never used in my documents (written in French: I need ASCII + some accented letters, probably less than 200 characters).

Questions

  1. Would luaotfload work if I build some lightweighted lua table files ?
  2. Is there a tool to tweak those lua table files? If not, how can I do it manually and tell luaotfload to load it?
  3. Will it speed up my compilation time?

EDIT

The answer to 2 might be building an appropriate subset of my fonts at font level with a tool like fontforge, thus creating a "new" lightweight font. As far as my googling can tell, this technique is used with web ttf fonts to minimize font size for downloads. So I add an item 4 to my questions: "Is subsetting a font a good way to downsize lua table files? Can I use fontforge to do the work with otf fonts? How? Is there any licence restriction?"

  • 1
    Probably unrelated but still interesting. – cjorssen Sep 16 '16 at 12:19
  • Have you compared compilation times when you don't load any custom fonts? When you don't load fontspec? Note that LuaTeX automatically regenerates those files when needed, so if you replaced them, your versions would be liable to disappear. – cfr Sep 17 '16 at 1:00
  • @cfr Stripping down my class file to fonts only: 4.8s (it takes more or less 5s to load all tikz/pgfplots/tcolorbox/ most of Heiko & David packages / expl3 files, so I reach 10s). fontspec only: 1.5s. No fontspec: 0.3s. – cjorssen Sep 18 '16 at 19:15
6

luatex loads a lot of otf fonts at every luaLaTeX run with my custom class […] On my system (linux, SSD, core i3), each run takes at least 10 seconds.

Are you referring to one entire pass of Luatex? I can’t say anything regarding Latex, but in Context that’s reached easily with more complex documents.

If I understand correctly, much of the time is spent reading byte compiled lua tables storing all the information needed to take care of an otf font.

Lua is a very efficient language. Parsing Lua programs is very efficient. Loading byte-compiled programs even more. It’s unlikely that this is the bottleneck you’re facing.

You can verify that easily: Determine the cache path (last line of luaotfload-tool -h), list the subdirectory otl/ and select a bytecode file. The extension is .luc. I choose one that is among the largest I know: kozminpr6n-regular.luc with 2,388,708 Bytes. These files are valid Lua programs so we can load them directly with Luatex. For maximum IO penalty we also clear the OS caches first:

$ sudo bash -c "echo 3 >/proc/sys/vm/drop_caches"
$ time texlua /home/phg/.local/texlive/2016/texmf-var/luatex-cache/generic/fonts/otl/kozminpr6n-regular.luc 

real    0m0.240s
user    0m0.100s
sys     0m0.017s

EDIT

Some further measurements: I decided to check whether passing the font loaded from cache to Luatex had a significant performance impact. Turns out it’s negligible.

Here’s a test setup that loads a list of fonts and measures the runtime. For more exact measurements it relies on the luaposix library. The timings are split into the cache retrieval per se (fonts.definers.read()) and feeding the result into font.define().

document with timings

To summarize the results: Forcing the 38 fonts through the loader adds 1.9 seconds to the runtime on my aged system; if the OS caches are hot this figure shrinks to around 1.5 s. Complex fonts from Adobe take around 50 ms to load. The huge kozminpr6n-regular.otf is an outlier at ca. 300 ms for retrieval plus 50 ms for passing through font.define().

END EDIT


240s to load the Luatex binary, spawn the Lua interpreter, and load one gigantic font table. On a low-end desktop from 2012. Not bad, especially considering that fonts are usually loaded on demand, not merely by virtue of being defined at some point.

Would luaotfload work if I build some lightweighted lua table files?

Those are cache files. They will be overwritten without asking next time anything changes. You will have to hack on the fontloader in order to make your changes stick.

Is there a tool to tweak those lua table files?

As shown above, you can load them with Lua and manipulate them like any ordinary table. The corresponding text representation (in the .lua files) is plain text so you can use your editor. But they need to be byte-compiled (texluac(1)) for use with the loader.

                                            If not, how can

I do it manually and tell luaotfload to load it?

The fontloader will look up a font file in the cache first, but it will also rewrite the cache if it doesn’t match the font file. Thus you’ll have to hack the loader to avoid this.

Will it speed up my compilation time?

Very unlikely. Loading byte code is very efficient and once the tables are in memory, only those parts will be used that are needed for processing the input.

The answer to 2 might be building an appropriate subset of my fonts at font level with a tool like fontforge

Throw out the tables you don’t like. That will reduce the table size. Make sure you don’t violate the vendors’ license terms. Some of them preclude any modification to the files.

Having a look at those tables […] it seems to me that most of the elements (unicode characters) there are nearly never used in my documents (written in French: I need ASCII + some accented letters, probably less than 200 characters).

If you only typeset Latin based copy, a more promising approach would be to stick with base mode instead of node which Luaotfload defaults to. That can speed up paragraph processing drastically.

  • Thanks you very much for taking the time to answer this technical question. Could you elaborate a bit on the difference between base mode and node mode? – cjorssen Oct 21 '16 at 11:08
  • @cjorssen I’ve added some stats. Regarding node vs. base: the latter applies the conventional TeX ligaturing plus kerning passes (see node.ligaturing, node.kerning in the Luatex manual) whereas node mode performs Opentype text shaping (and more). – Philipp Gesang Oct 21 '16 at 23:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.