texlive 2016 および forest 2.0 への移行後のメモリの問題

texlive 2016 および forest 2.0 への移行後のメモリの問題

800 ページを超える本があり、texlive 2015 の xelatex と forest 1.05 で問題なくコンパイルできます。トランスレータが forest 2.0 で動作するため、texlive 2016 に移行しています。現在、次のようになっています。

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

フォレスト コードを削除すると、後でエラーが発生します。小さな部分をテキスト化すると、すべて正常になります。つまり、これは本当にメモリの問題だと思います。

質問: いくつかの tex 構成ファイルを変更する以外に何かできることはありますか? コードは複数のユーザーに対して実行されることになっているため、メモリ変数を変更するのは良くありません。

申し訳ありませんが、ここでは最小限の例はありませんが、コードを github または他の場所で公開することはできます。

編集: OK。texlive 2016 の実行中に forest 1.05 をロードするとすべて正常になるので、forest 2.0 であるに違いありません。

答え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}%

(多くのパッケージがこのようなシステムを使用しています。たとえば、PGF を参照してください\pgfutil@in@。)

新しいシステムは 10% ほど遅くなりますが、Stefan の 800 ページを超える本では、バージョン v2.1.3 が 600 万文字の文字列プール制限を超えましたが、バージョン 2.1.4 (および他の多くのロードされたパッケージ) ではわずか 200 万文字しか使用しません。パッキング アルゴリズムによるメモリ消費に関しては、ドキュメントの長さはもはや問題ではありません。

Stefan、これを見つけて、この 1 週間我慢してくれてありがとう! (ヒント: 数年経ってパッキング アルゴリズムを改めて見てみると、もっと高速化できると思います!)

関連情報