迁移到 texlive 2016 和 forest 2.0 后出现内存问题

迁移到 texlive 2016 和 forest 2.0 后出现内存问题

我有一本 800 多页的书,在 texlive 2015 下使用 xelatex 和 forest 1.05 编译得很好。我正在迁移到 texlive 2016,因为我的翻译器适用于 forest 2.0。现在我得到:

! TeX capacity exceeded, sorry [pool size=6143546].
\safeiterate@4 ...@countc y\endcsname )\endcsname 
                                              \forest@inpath      \forest@tem...
l.770 }

如果我删除森林代码,稍后就会收到错误。如果我删除较小的部分,一切都会正常。所以我猜这确实是内存问题。

问题:除了修改一些 tex 配置文件外,我还能做什么?代码应该为多个用户运行,修改内存变量会很糟糕。

抱歉,这里没有最小示例,但我可以将代码发布在 github 或其他地方。

编辑:好的。它一定是 forest 2.0,因为当我在运行 texlive 2016 时加载 forest 1.05 时,一切都正常。

答案1

这确实是一个森林问题,但令人惊讶的是,从软件包的第一个版本开始就存在了。Stefan 只是第一个创建如此长的、充满树状结构的文档的人……而从 v1 切换到 v2 只会将问题推向边缘。

在解释出了什么问题之前:我刚刚将修复版本(v2.1.4)发布到了 CTAN。

问题正是 Ulrike Fischer 在上面的评论中提到的。Forest 的打包算法需要(暂时)存储一些有关坐标(和坐标对)的信息。此外,给定一个坐标(或一对坐标),它需要快速检索有关它的信息。显而易见的解决方案是将信息存储在字典(关联数组)中,坐标是查找键,因此使用 TeX 的控制序列似乎是一个完美的想法,我天真地这样做了(基本上是从我的概念验证 Python 实现中复制粘贴的):

\csdef{forest@(\the\pgf@x,\the\pgf@y)}{...}

乃至

\csdef{forest@(\the\pgf@xa,\the\pgf@ya)--(\the\pgf@xb,\the\pgf@yb)}{...}

没有意识到虽然定义是本地的,但条目将永远保留在 TeX 的哈希表中。这种方法很容易耗尽几千字节的字符串池空间每棵树

v2.1.4 通过将所有信息存储在单个 toks 寄存器中重新实现了有问题的字典,其内容如下所示(仅显示上述第一个问题):

...(x1,y1){...}(x2,y2){...}...

在这样的结构中搜索特定坐标很容易(尽管比\csname方法慢):

\def\forest@breakpath@getfromtoks#1#2#3#4{%
  % #1=cache toks register, #2=receiving cs, (#3,#4)=point;
  % we rely on the fact that the point we're looking up should always be present
  \def\forest@breakpath@getfromtoks@##1(#3,#4)##2##3\forest@END{##2}%
  \edef#2{\expandafter\forest@breakpath@getfromtoks@\the#1\forest@END}%

(许多软件包都使用这样的系统,例如参见 PGFs \pgfutil@in@。)

新系统大约慢了 10%,但是:在 Stefan 的 800 多页书中,版本 v2.1.3 超过了 600 万个字符串池限制,而 v2.1.4(以及所有其他加载的软件包)仅使用了 200 万个字符串池限制。对于打包算法的内存消耗,文档长度实际上不再重要。

Stefan,谢谢你发现这个问题,并在过去一周里一直支持我!(提示:经过这几年重新审视打包算法,我相信它也可以变得更快!)

相关内容