LaTeX3 项目正在做什么来使 LaTeX 运行得更快?

LaTeX3 项目正在做什么来使 LaTeX 运行得更快?

我对 LaTeX 最大的不满之一是它处理大型文档的速度太慢。(我用 LaTeX 排版书籍。)我有一些方法,比如将书分成几章,然后单独运行。但结果并不令人满意。

例如,我目前正在写的书在运行 LaTeX 后报告了以下情况:

Latexmk: All targets () are up-to-date
no errors
make  74.57s user 1.92s system 99% cpu 1:17.05 total

我的电脑有六个核心!LaTeX 使用其中一个。

编辑

我的系统的详细信息:

  • MacMini(2018)3 Ghz 六核 Intel Core i5 处理器,32 GB 2667 MHz DDR4 RAM
  • 41 个.tex输入文件,总共 11,000 行 LaTeX 源文件,超过 100,000 个单词的文本。
  • 由于 Unicode 问题而移至 xelatex,但pdflatex花费的时间大致相同。
  • 包含 69 个套餐
  • 该书目前排版为 326 页,项目完成后将排版为 500 页。
  • 72 张图片,大多数在 20-50k 左右。
  • 输出日志文件长 5611 行(!)
  • 仍在使用,BiBTeX因为biber中断了,我无法调试它。但biblatex至少可以使用。
  • 使用以下方式编译latexmk
  • 中的多个目标Makefile,包括仅排版每个章节的目标。排版单个章节只需 15.97 秒即可完成

LaTeX 专家会说,由于 LaTeX 是图灵完备的,所以每一页都依赖于它之前的所有内容。当然,由于临时文件的存在,每一页也依赖于它之后的每一页。坦率地说,LaTeX 在排版时收敛得如此之快,真是太神奇了!

但是,有一些众所周知的技巧可用于解决此问题。例如,页面可以检查相关状态,然后新的编译可以使用多线程实现并使用上一次运行的检查点运行每个页面,如果检查点发生变化,则重新运行页面。可以使用类似的东西来加速甚至单线程运行:如果我们正在编译第 265 页,并且第 265 页开头的状态与上次运行相同,并且文档中的文本在第 265 页的开头和第 266 页的开头之间没有变化,那么第 266 页上可能没有任何变化。

似乎这些优化可以让 LaTeX 的速度大大加快。那么为什么我们在 LaTeX2e 中看不到它们,它们会在 LaTeX3 中出现吗?

答案1

LaTeX 项目确实花费了大量时间来确保 latex 尽可能快地运行,但您建议的任何内容都与 latex 代码无关;您建议对编写 latex 的 tex 语言进行更改。

如果你查看 github 问题就会发现,人们花了很多心思来优化核心 expl3 编程结构,无论是使用多个\expandafter\fi-delimited 参数还是在每种情况下使用\expanded或其他方式都更快。

此外,今年发布的 LaTeX 已预装了两个较大的包expl3(分别在二月和xparse十月),这可以显著改善启动时间,因为定位包文件和从文件系统读取数据所花的时间比处理文件内的 tex 代码要长得多。

请注意,您可以构建自定义格式来预加载您所使用的包,这也可以大大加快启动时间。

您提到的那种检查点询问的是底层 tex 系统,因此无法在 LaTeX 中寻址。它与其他编程语言相同。网页作者可以避免在页面中使用效率低下的 JavaScript 来加快页面加载速度,但他们无法在所有可能运行该代码的浏览器中重写 JavaScript 引擎,这与您在此处询问的内容相同。

实际的检查点很难,因为分页是异步的,强制分页是可行的,\clearpage这正是 LaTeX\include系统所做的,它会保存此时所有 LaTeX 计数器的状态,因此如果在下次运行时跳过第 1-3 章,页码将被保留,草稿文档从第 4 章开始。但要自动执行此操作并保存更多状态,例如所有宏的定义,而不仅仅是所有计数器的值,则需要对 tex 系统进行更改,而不是对 latex 进行更改。

您提到由于辅助文件的存在,后面的更改可能会影响前面的更改,但这其实是更简单的情况,只需考虑一个跨越两页或更多页的长段落。在最后一行添加逗号可以更改整个段落的换行符,因此更改前面的页面时不会涉及任何辅助文件。

如今,许多 tex 系统都足够快,以至于 latex 被设置为在编辑文件时在后台连续运行,并在成功重新制作 pdf 时更新显示,如果您的构建速度很慢,您应该查看您的构建系统,您是否包括高分辨率图像或每次运行时都重新设置复杂的 tikz?如果您安排将这些内容保存到更偶尔的“完整”构建中,您通常可以让事情以合理的速度运行。

答案2

把这个当作一个有点挑衅性的宣言:

最近我回到了 LaTeXworld,一直在考虑是否能完成我在 80 年代末 / 90 年代初教授 TUG LaTeX 课程时开始编写的 LaTeX 书。

LaTeX 2e 于 1994 年首次发布,作为最终发布 LaTeX 3 的过渡步骤。26 年后,LaTeX 3 仍然没有 1.0 版本。在此期间,我们见证了 HTML 和网络的兴起,以及 PDF 作为印刷材料表示格式的主导地位(现在有计划通过“流动模式”扩展 PDF,允许在较小的屏幕上重新排列 PDF 文本)。

与此同时,TeX 引擎也经过多次扩展,包括很少使用的 TeX-XeT、一些早期支持大型亚洲字符集的努力,以及广泛使用的 pdfTeX、XeTeX、LuaTeX 以及各种废弃的引擎。最糟糕的是,似乎没有一个 pdfTeX、XeTeX 或 LuaTeX 可以成为统治所有 TeX 的唯一 TeX,每个引擎都有一些限制,可能需要用户根据自己的需要切换引擎。

在我看来,问题的根源在于 TeX 本身。用当代软件工程术语来说,TeX 是一个紧密耦合的巨石。更糟糕的是,由于 20 世纪 70 年代计算机硬件的限制,TeX 是一个紧密耦合的巨石,其中存在许多妥协。似乎 LaTeX 3 的绝大部分工作都是为了解决 TeX 作为一种编程语言的局限性。

除此之外,LaTeX 社区中出现了大量可疑的、甚至是完全有害的做法。理想情况下,文档应该从一个文档类转换为另一个结构相似的类(从命名角度来看,选择“类”来命名文档类是不幸的,但可以理解),不应该要求在序言之后更改任何内容,更好的是,除了命令本身之外什么都不做。所有外观都应该通过文档类来处理,并且\documentclass应该使用包来提供文档结构增强或新功能)。有很多违反这一点的行为。类memoir是一团糟,声称是 的替代品(这让我想起了 PHP 的混乱,其中相同的数据结构充当数组和关联数组,因此设法将两者最糟糕的方面合并在一个低效的构造中),同时提供许多属于包而不是文档类的功能。另一方面,像和这样的包属于 LaTeX2e 实际上没有定义的类别,一些通用代码可能对文档类编写者有帮助,但实际上不应该向文档作者公开。articlereportbookgeometryfancyhdr

鉴于 NTS 和 ExTeX 最终的失败,我对解决任何这些问题都不抱有希望。

编辑 2020 年 10 月 20 日我做了一件蠢事。我开始一个新项目. 它可能永远不会有任何结果。

相关内容