lualatex:处理大型文档时速度慢且超出 tex 容量

lualatex:处理大型文档时速度慢且超出 tex 容量

我最初的问题陈述是这样的:

我在使用 lualatex 编译大型文档(.tex 文件为 4.4M)时遇到了麻烦。这只是一个实验,而不是我需要生成的文档。有两个问题:lualatex 非常慢(比 pdflatex 慢 100 倍以上),最后失败了。

我在网上找到了一份纯文本的圣经,并编写了一个 Python 脚本,用一个小宏调用来包装章节和诗句编号。[...]

使用 lualatex 进行编译在运行 20 分钟(1200 秒,或 pdflatex 运行时间的 109 倍)后以以下“致命错误”结束。[...]

但是我现在可以使用脚本生成的 .tex 文件重新创建该问题:

下面是一个生成 .tex 文件的脚本,该文件使用 lualatex 编译非常慢,最终失败并出现此错误:

! TeX capacity exceeded, sorry [number of strings=493861].
\__fontspec_primitive_font_set:Nnn ...\font #1=#2 
                                                  at \dim_eval:n {#3}\scan_s...

l.271101  \myvn{26751}c
                     ategorical
 39802 words of node memory still in use:
   46 hlist, 1 rule, 395 disc, 2 local_par, 1 dir, 413 glue, 717 kern, 24 penal
ty, 3981 glyph, 73 attribute, 48 glue_spec, 73 attribute_list, 1 temp, 1 if_sta
ck nodes
   avail lists: 2:105,3:27,4:7,5:1611,6:2,7:2165,9:39,10:6,11:716
!  ==> Fatal error occurred, no output PDF file produced!
Transcript written on big.log.

real    19m13.003s
user    18m54.195s
sys     0m7.209s

这是 python (v2) 脚本,我在 Mac 上运行了它,并期望它可以在 Linux 上运行,但它使用 /usr/share/dict/words 作为单词来源,而我认为 Windows 上没有等效列表。(也许重复同一个词 800000 次就足够了。)

MWE 生成器:

#!/usr/bin/python

with open("/usr/share/dict/words") as fp:
    wbank = fp.readlines()
    wcnt = len(wbank)

preamble8 = """\\documentclass{article}
\\RequirePackage{fontspec}
\\RequirePackage{realscripts}
\\defaultfontfeatures[mysspD]{
  Numbers        = {Proportional,OldStyle},
  UprightFont    = SourceSerifPro-Regular ,
  ItalicFont     = SourceSerifPro-RegularIt ,
  SlantedFont    = SourceSerifPro-Regular,
  SlantedFeatures= {FakeSlant=0.2},
  BoldFont       = SourceSerifPro-Semibold ,
  BoldItalicFont = SourceSerifPro-SemiboldIt ,
  Ligatures      = TeX ,
  Scale          = 1 ,
  Extension      = .otf
}
\\setmainfont{mysspD}

\\makeatletter
\\newcommand\\myvn[1]{%
  \\@ifnextchar A%
  {\\textsuperscript{\\liningnums{\\itshape #1\\/}}\\kern -0.08em}%
  {\\textsuperscript{\\liningnums{\\itshape #1\\/}}\\kern 0.14em}}
\\makeatother
\\begin{document}
"""

vn = 1
with open("big.tex", "w") as fp:
    fp.write(preamble8)
    for i in range(800000):
        fp.write(wbank[i % wcnt])
        if i % 10 == 0:
            fp.write("\\myvn{%d}" % (vn,))
            vn += 1
        if i % 150 == 0:
            fp.write("\n\n")
    fp.write("\\end{document}\n")

答案1

罪魁祸首在于你反复使用\liningnums。这实际上就是用 重新加载文件中的字体Numbers=Lining。这意味着每次调用 时\myvn你都会重新加载字体,但很快就会忘记它。字体加载是 TeX 中最昂贵的操作。

我也删除了,realscripts因为它有同样的问题。它重新定义\textsuperscript为使用\addfontfeature{VerticalPosition=Superior},因此每次调用时它也会从磁盘重新加载整个字体。

我怀疑会为此fontspec分配一个临时文件\font。此字体的名称存储在 TeX 的字符串池中,即使在离开组后再也不会使用,TeX 也不会忘记它,请参阅此问题:释放字符串池中的空间

您实际上应该能够观察到 XeLaTeX 的相同问题,尽管我不得不承认我没有足够的耐心等待错误触发。

解决您的问题的方法显然是减少字体加载。因此,您可以像这样定义一个新的字体系列

\newfontfamily\LnumItMainfont{SourceSerifPro-RegularIt.otf}[Numbers=Lining]

然后而不是

\liningnums{\itshape #1\/}

您可以使用

\LnumItMainfont #1\/

这不仅可以节省您重新加载字体的时间,还可以节省您重新加载字体系列的时间。

在我的计算机上我现在得到:

$ time lualatex --interaction=batchmode big.tex
This is LuaTeX, Version 1.10.1 (TeX Live 2019) 
 restricted system commands enabled.

luaotfload | main : initialization completed in 0.079 seconds

real    0m39.016s
user    0m38.864s
sys 0m0.152s

相关内容