我最初的问题陈述是这样的:
我在使用 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