У меня есть книга на 800+ страниц, и она отлично компилируется с xelatex и forest 1.05 под texlive 2015. Я перехожу на 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 или где-нибудь еще.
Редактировать: ОК. Это должен быть лес 2.0, так как когда я загружаю лес 1.05 при запуске texlive 2016, все в порядке.
решение1
Это действительно была проблема леса, но, как ни странно, она присутствовала с самой первой версии пакета. Стефан был просто первым, кто создал такой длинный, полный дерева документ... и переход с v1 на v2 не сделал ничего, кроме как вытолкнул проблему за край.
Прежде чем объяснить, что пошло не так: я только что опубликовал исправленную версию (v2.1.4) на CTAN.
Проблема была именно в том, о чем Ульрике Фишер упомянула в комментарии выше. Алгоритм упаковки 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 навсегда. Такой подход легко израсходовал несколько килобайт пространства пула строкза дерево!
В версии 2.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% медленнее, но: в книге Стефана объемом более 800 страниц, где версия v2.1.3 превысила лимит пула строк в 6 миллионов символов, v2.1.4 (и все остальные загруженные пакеты) использует всего 2 миллиона. Что касается потребления памяти алгоритмом упаковки, длина документа больше не имеет значения.
Стефан, спасибо, что нашел это и терпел меня всю прошлую неделю! (Подсказка: взглянув на алгоритм упаковки по-новому спустя несколько лет, я считаю, что его можно было бы сделать намного быстрее!)