遷移到texlive 2016和forest 2.0後出現記憶體問題

遷移到texlive 2016和forest 2.0後出現記憶體問題

我有一本 800 多頁的書,它可以在 texlive 2015 下使用 xelatex 和forest 1.05 編譯良好。現在我得到:

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

如果我刪除森林代碼,稍後會收到錯誤訊息。如果我吃較小的部分,一切都很好。所以我猜這確實是一個記憶體問題。

Q:除了修改一些 tex 設定檔之外,我還能做些什麼嗎?該程式碼應該為多個用戶運行,並且必須修改記憶體變數會很糟糕。

抱歉,這裡沒有最小的範例,但我可以在 github 或其他地方提供程式碼。

編輯:好的。它必須是森林 2.0,因為當我在運行 texlive 2016 時加載森林 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,感謝您發現這個並在過去的一周裡對我的包容! (提示:幾年後重新審視打包演算法,我相信它也可以做得更快!)

相關內容