哪个定义占用更多内存,\def 还是 \chardef(考虑到 \def 包含一个字符)?

哪个定义占用更多内存,\def 还是 \chardef(考虑到 \def 包含一个字符)?

问题完全在标题中。我们取\def\testName{a}\chardef\testName`\a。哪个定义需要更多内存?

答案1

答案很简单:\chardef使用更少的资源。

编译

%\def\usedef{\expandafter\def\csname\the\count255\endcsname{a}}
\def\usedef{\expandafter\chardef\csname\the\count255\endcsname=`a }

\count255=1
\loop\ifnum\count255<500000
\usedef
\advance\count255 1
\repeat

\tracingstats=1

\bye

我明白了

Here is how much of TeX's memory you used:
 499994 strings out of 2095124
 2888925 string characters out of 6220659
 5959 words of memory out of 5000000
 500917 multiletter control sequences out of 15000+600000
 14794 words of font info for 50 fonts, out of 8000000 for 9000
 14 hyphenation exceptions out of 8191
 5i,0n,1p,81b,6s stack positions out of 5000i,500n,10000p,200000b,80000s

切换前两行的注释,TeX 将执行\def而不是\chardef,并且日志将显示

Here is how much of TeX's memory you used:
 499994 strings out of 2095124
 2888921 string characters out of 6220659
 1505944 words of memory out of 5000000
 500917 multiletter control sequences out of 15000+600000
 14794 words of font info for 50 fonts, out of 8000000 for 9000
 14 hyphenation exceptions out of 8191
 5i,0n,1p,82b,6s stack positions out of 5000i,500n,10000p,200000b,80000s

笔记。我必须为字符串提供更多的内存空间,max_strings=10000000以便为 500000 个新的控制序列腾出空间。

答案2

由于\chardef只能将控制序列与 0 到 255 之间的整数值相关联,而\def可以将其与任意标记列表相关联,因此后者更为通用,并且它也更昂贵也就不足为奇了。事实上,TeXbook引入\chardef“对于0到255之间的数字,作为有效的替代” \def,事实确实如此。


作为对@egreg答案的进一步细化,它使用\def\chardef 500000次并检查统计数据,我们可以对这两个中的每一个(固定)进行比较使用 1000 次和 2000 次(或 1000 次和 1001 次,或其他)后的统计数据,以查看额外的每个定义的(增量)成本。

您会发现,对于 或\def\testName{a}\chardef\testName`\a共同的成本(对于每个这样的定义)是:

  • 1 个字符串条目(即新字符串testName),

  • 8个字符串字符(即存储字符串t e s t N a m e)(取决于你的名字的长度),

  • 1 个“多字母控制序列”(假设您的名字长度大于 1)。

(请注意,TeX 进行了一些优化以避免存储已经存在的东西,因此在某些情况下它可能能够避免部分成本,但一般情况下并非如此。)\chardef\testName`\a这是唯一的成本,但对于每个成本\def\testName{a}都有上述成本以及以下成本:

  • 记忆3个单词

原因不难看出。只需\chardef将整数值放入表中即可。例如,您的\chardef\testName`\a等于\chardef\testName=97。(例如,plain.tex使用\chardef\active=13。)因此,当您编写 时\chardef\testName=97,TeX 内部进行的簿记如下:

  • 在字符串池中:附加八个字符testName
  • 在字符串列表中(未明确存储):从最新的字符串编号(增加1)指向字符串池中上述8个字符的起始位置
  • 在控制序列列表中:从哈希值指向testName上述字符串数字
  • 在(内部)等价表中(eqtb),其中(除其他外)存储了控制序列的含义:存储一个新条目
    • eq_level当前/适当的水平,
    • eq_type特殊代码char_given(表示它\testName是一个 chardef 的数字),
    • equiv是值本身(这里是整数97)。

您可以在《程序

沙尔德夫

另一方面\def,TeX 必须在内部创建一个包含标记的标记列表a(即 catcode 11=字母,值 97)。此外,每个标记列表都以引用计数开头,以 NULL 结尾,这解释了为什么使用了三个字的内存。


因此,为了总结差异,只需看看以下两个案例(抱歉,该图不是用 TikZ 制作的

相关内容