看完之后增加 LaTeX 容量无法召唤甘道夫1,我很好奇,在 (La)TeX 编译过程中,哪些因素会影响内存使用量。以上述帖子的输出为例:
l.3593 ...temp.png}
If you really absolutely need more capacity,
you can ask a wizard to enlarge me.
Here is how much of TeX's memory you used:
31937 strings out of 94500
1176767 string characters out of 1176767
272586 words of memory out of 1000000
24170 multiletter control sequences out of 10000+50000
11185 words of font info for 39 fonts, out of 500000 for 2000
580 hyphenation exceptions out of 1000
28i,7n,36p,345b,3810s stack positions out of 1500i,500n,5000p,200000b,5000s
PDF statistics:
33619 PDF objects out of 300000
7356 named destinations out of 131072
48094 words of extra memory for PDF output out of 65536
! ==> Fatal error occurred, the output PDF file is not finished!
在包含包、用户定义的宏和环境的“常规文档”中,什么构成了 a string
、a string character
、a word
、a multiletter control sequence
、words of font
a、ahyphenation exception
和stack positions
(运行时pdftex
)a PDF object
、anamed destination
和word of extra memory
?
这个问题的目的是为了了解如果你正在编译一个4000 页文档- 哎呀!也许,更现实的情况是,你正在排版非常大的文档尽管你只使用每个包中的少数几个宏/环境,但你还是包含了大量包。(La)TeX 仍然会加载全部的打包到内存中,这样您就可以减少工作量。
阅读pdf 对象/目的地/内存限制仅建议可能存在问题的地方以及如何提高 (La)TeX 的可用容量。但是,它没有说明文档的哪些部分对哪个内存组件有贡献。与我发现的其他帖子类似。
一些内存输出可能是不言自明的,但并非全部。例如,multiletter control sequences
可能参考\newcommand{\mycom}{...}
和这样的定义\def\stuff{...}
,我假设每个定义都会将计数增加 1。但是,这似乎排除了,\def\a{...}
因为它是single letter control sequence
?此外,\def\stuff{...}
将 +1 添加到string
和将 +5 添加到string characters
?
理解这一点可能不会影响我目前的任何使用习惯,因为它们从未给我带来过这种性质的内存问题,除非问题出在我这边而不是编译器那边。然而,它可能会改善未来 (La)TeX 宏/环境编程。
1顺便说一句,TeX 的输出If you really absolutely need more capacity, you can ask a wizard to enlarge me.
简直是史诗级的。
答案1
这是一个简短的程序,可以打印 15283 1页,且不会出现任何内存问题的迹象。
\documentclass{article}
\usepackage{lipsum}
\begin{document}
\newcount\n
\n=0
\def\message{I can count to }
\loop
\ifnum\n<37000
\advance\n by1
\message\number\n : \lipsum[1-2]
\repeat
\end{document}
您可以增加\lipsum[1-2]
并测试您的耐心以及 TeX 的极限!只要您允许 TeX 轻松破坏页面,您就不太可能遇到任何内存问题。
Knuth 创建了一个非常高效的内存管理系统。详细信息可参见TeX 源。关于如何处理内存和字符串的有限解释可以在我的回答中找到用宏本身来限定宏参数. 还请检查您的发行版上的 TEXPOOL。
不仅 Knuth,Lamport 和所有 LaTeX 贡献者都非常注意节省内存以及提供适当的垃圾收集。在我看来,学习 TeX 源代码应该是所有计算机科学课程的必读内容。在上面的链接中,检查动态内存分配部分并注意 Knuth 的评论(第 119 条),这是 TeX 新用户遇到的最常见问题:
如果内存耗尽,则可能意味着用户忘记了右括号……
最后要说的是,TeX 不会将您的“书”保存在内存中。它总是一次处理一页......好吧,差不多。如果您没有用右括号结束,它将继续扫描,可能直到源的末尾,因此它无法释放内存。Knuth 引入了许多检查和特殊命令来避免这些问题(long
,outer
等等...)。
1给读者一个练习,将页面高度改为一半,看看是否可以将页面数量增加一倍。
答案2
我试图理解其中的魔法,可能有点蛮力,但它确实触及了内存使用输出中包含的一些问题。它没有描述如何修改(或增加这些数量)。
下面的大部分讨论都围绕着对以下基本的“Hello world”最小示例的修改。我们称之为Hello world
1。上标表示初始 MWE,后续修改用增大的上标表示:
\documentclass{article}% Hello world 1
\begin{document}
Hello world.
\end{document}
TeX 统计数据
( ) 串来自 ( )
照原样,Hello world
1使用203
中的字符串493633
。将其修改为Hello world
2:
\documentclass{article}% Hello world 2
\begin{document}
Hello world. Hello world.
\end{document}
保持不变全部统计信息。但是,Hello world
作为宏的一部分(通过\def
或\newcommand
)定义为Hello world
3
\documentclass{article}% Hello world 3
\def\helloworld{Hello world.}% \helloworld -> Hello world.
\begin{document}
\helloworld
\end{document}
导致 TeX 内存使用量的这一部分增加一个单位,达到204
。宏定义会增加字符串,但使用量不会增加。也就是说,\helloworld
文档中有 50 个命令仍然只会使用204
字符串。使用\input
或\include
(Hello world
4):
\documentclass{article}% Hello world 4
\begin{document}
\input{helloworld.txt}% Hello world.
\end{document}
\include
使用较少的字符串,但必然要求文件具有.tex
文件扩展名。
() 个字符串字符,总计 ()
Hello world
1有2308
字符串字符,同样如此Hello world
2。 然而,Hello world
3使用2318
字符串字符,源自 10 个字母的控制序列\helloworld
。在定义宏时,简洁(清晰)至关重要。也就是说,最好避免Hello world
5:
\documentclass{article}% Hello world 5
\def\helloworldmacrothatwillwritehelloworldastheoutput{Hello world.}%
\begin{document}
\helloworldmacrothatwillwritehelloworldastheoutput
\end{document}
( )个单词的记忆范围从( )个
仅需Hello world
1,已经49245
使用了记忆单词。这保持不变,使用Hello world
2,3。但是,如果\helloworld
定义为包含相当大的段落(例如lipsum
包裹),这些词被提升(在本例中被提升为1000
to )50245
Hello world
6:
\documentclass{article}% Hello world 6
\newcommand\helloworld{%
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris
turpis purus, posuere et suscipit eu, dictum ac lacus. In velit
orci, pulvinar nec tristique quis, congue id diam. Sed sit amet
augue tellus, sit amet placerat sapien. Vivamus scelerisque placerat
libero id auctor. Donec laoreet auctor velit, eu cursus nulla
bibendum a. Mauris id tellus vitae felis sodales sagittis. Curabitur
mollis vehicula sagittis. In pharetra elit vel dui mattis dapibus.
Pellentesque commodo magna eu sem faucibus fermentum. Nunc in turpis
arcu, nec venenatis enim. Quisque sed velit id velit ullamcorper
suscipit mattis a ipsum. Etiam viverra eleifend tellus, eget sodales
enim varius at. Proin quis nibh mi. Nullam sed nisl id mauris
aliquam feugiat.}
\begin{document}
\helloworld
\end{document}
事实上,使用代码由@Yiannis 提供写出几页有益身心的文章只需要记忆15283
一个单词,比145453
Hello world
6在我的系统上,我甚至可以将 37000 的限制提高到 100000,41305
在短短 3 分钟内生成一个 ~61.5MB 的页面文档,而内存使用量没有任何明显增加。这无疑是由于换行和段落中断会刷新一些内存;根据 @egreg 关于\par
删除的评论,只有900
迭代会产生2746549
内存字数(使用率 >90%)。从编译输出中也可以明显看出,TeX 在消化摄入的内容时“深吸了一口气”,然后喷涌出222
令人叹为观止的美丽页面。Knuth 也在 TeX Book 第 300 页中提到了这一点:
如果您指定了一个巨大的段落或一个跨越多页的巨大对齐,您应该改变您的方法,因为 TeX 必须一直读取到最后才能完成换行或对齐计算;这会消耗大量的内存空间。
( ) 个多字母控制序列,来自 ( )
(La)TeX 默认定义了许多单字母控制序列:\\
, \c
(表示变音符)、\b
(表示横线)等。而且,由于可用的单字母控制序列数量有限,因此计算多字母控制序列更有建设性。这是一个显而易见的计数方法。Hello world
1生成3587
这样的控制序列,充分体现了 (La)TeX 为帮助您入门所做的所有幕后准备工作。事实上,8000 多行latex.ltx
充斥着宏定义(和\let
s)。Hello world
3正如预期的那样,具有3588
多字母控制序列。
除了上述 TeX Book 的摘录外,Knuth 还写道(第 300 页):
如果您已经建立了一个庞大的宏库,您应该记住 TeX 必须记住您定义的所有替换文本;因此,如果内存空间不足,您应该只加载您需要的宏。
对于丰富的文档类来说尤其如此,例如beamer
并且(比如说)hyperref
包裹. 事实上,这Hello world
7在beamer
:
\documentclass{beamer}% Hello world 7
\begin{document}
Hello world.
\end{document}
用途
15105
字符串出493633
;280253
字符串字符出3146724
;353989
记忆中的单词3000000
;和18064
多字母控制序列15000+200000
。
共 ( ) 个字,包含 39 种字体的字体信息,共 ( ) 个字
( ) 连字例外情况( )
Hello world
1涵盖831
连字符例外情况,而Hello world
8:
\documentclass{article}% Hello world 8
\begin{document}
\hyphenation{He-ll-o} \hyphenation{w-o-r-ld}
Hello world.
\end{document}
有833
。可以理解的是,这取决于语言。此外,只有全局连字/自由设置会影响连字例外,而本地/临时设置(如He\-ll\-o
)不会影响它。
( ) 个堆叠位置,来自( )
这些指的是(来自 TeX Book,第 300 页):
i
:输入堆栈大小(同时输入源);n
:语义嵌套大小(正在构建未完成的列表);p
:参数堆栈大小(宏参数);b
:缓冲区大小(从文件读取的行中的字符);以及s
:保存大小(组结束时要恢复的值)
我没有冒险去查看这些是如何修改的。但是,正如 TeX Book(第 300 页)中建议的那样,\tracingrestores=1
在您的文档中使用将生成一份跟踪报告(在您的.log
文件中),该报告显示了 TeX 如何在每组末尾从堆栈中删除已保存的项目。
PDF 统计
( ) 个 PDF 对象中的 ( )
非常直接PDF 对象的讨论提到主要有三种类型:
- 注解
- 文本,以及
- 图片
因此,毫不奇怪Hello world
9
\documentclass{article}% Hello world 9
\usepackage{graphicx}% http://ctan.org/pkg/graphicx
\begin{document}
\noindent%
\includegraphics[width=\linewidth]{tiger}% http://mirrors.ctan.org/info/examples/lgc2/pstricks/tiger.eps
\end{document}
将起始 PDF 对象数量增加约 100 个(至 100 个17
)。其他对象包括文档页面。
( ) 个目的地(共 ( ) 个)
PDF 中的目标是指标记的位置。这些通常与诸如 、 和 之类的分段\section{...}
宏\phantomsection
相关\chapter{...}
联\caption{...}
。Hello world
10
\documentclass{article}% Hello world 10
\usepackage{hyperref}% http://ctan.org/pkg/hyperref
\begin{document}
\section{Hello world.}
\end{document}
生成3
命名的目的地(从空白处开始的一个单位增量Hello world
1并且仅包括hyperref
包裹)。
用于 PDF 输出的额外内存 ( ) 个字,其中 ( ) 个
所有以上统计数据均源于运行 TeX Live 2011 和 pdfTeX,版本 3.1415926-2.3-1.40.12,并且几乎肯定会与其他安装有所不同(无论大小)。