LaTeX as a decades old system should not use too much memory. But sometimes, we will see it run out of memory. There are various solutions to this. Here are what I tried.
My recent experience in making LaTeX run out of memory is to use pgfplots
—
with a complicated function and a lot of data points, it will eat up all the
memory inside the LaTeX stack. However, it doesn’t mean your system failed to
malloc. Rather, it just means the TeX stack has overflown.
In the old time, I remember LaTeX allows to allocate more memory at run. If we run latex command with an extra options:
latex -extra_mem_top=10000000 -extra_mem_bot=10000000 file.tex
it should run with a bigger stack (hence more elements per page is allowed). However, as I can confirm with the TeX memory usage statistic upon out of memory error, it seems to me that these options are not having any effect. They are simply ignored. As far as in TeXLive 2021 on mac.
The other way to get more memory is specific to MiKTeX. This is the command line that provided by Chapter 6 of the pgfplots manual:
pdflatex
--stack-size=n --save-size=n
--main-memory=n --extra-mem-top=n --extra-mem-bot=n
--pool-size=n --max-strings=n
For TeXLive, we have to modify the texmf.cnf
file for configurations. The
exact path can be found by kpsewhich texmf.cnf
and this is what we can add to
the file:
% newly created file ~/texmf/mytexcnf/texmf.cnf:
% If you want to change some of these sizes only for a certain TeX
% variant, the usual dot notation works, e.g.,
% main_memory.hugetex = 20000000
main_memory = 230000000 % words of inimemory available; also applies to inimf&mp
extra_mem_top = 10000000 % extra high memory for chars, tokens, etc.
extra_mem_bot = 10000000 % extra low memory for boxes, glue, breakpoints, etc.
save_size = 150000 % for saving values outside current group
stack_size = 150000 % simultaneous input sources
% Max number of characters in all strings, including all error messages,
% help texts, font names, control sequences. These values apply to TeX and MP.
pool_size = 1250000
% Minimum pool space after TeX/MP's own strings; must be at least
% 25000 less than pool_size, but doesn't need to be nearly that large.
string_vacancies = 90000
% Maximum number of strings.
max_strings = 100000
% min pool space left after loading .fmt
pool_free = 47500
% Extra space for the hash table of control sequences (which allows 10K
% names as distributed).
hash_extra = 200000
We should run sudo texhash
or sudo fmtutil-sys --all
after the texmf.cnf
is updated.
A final method is to use luatex instead of pdflatex, for luatex will expand
memory automatically. This can be simply done by replacing the executable
pdflatex
with lualatex
. It may run slower sometimes but it will allocate
memory automatically without the need to specify the size before start.
Specific to pgfplots, we can also externalize the plots to save memory. It works sometimes when the page itself is competeing with pgfplots for the memory. It will not work if the pgfplots itself is large enough to blow up the memory usage. To use externalization, add this to the preamble:
\usepgfplotslibrary{external}
\tikzexternalize[prefix=path/to/tempfiles/,shell escape=-enable-write18]
\tikzset{external/system call= {pdflatex -save-size=80000
-pool-size=10000000
-extra-mem-top=50000000
-extra-mem-bot=10000000
-main-memory=90000000
\tikzexternalcheckshellescape
-halt-on-error
-interaction=batchmode
-jobname "\image" "\texsource"}}
which the prefix=
at tikzexternalize
is a path to prepend to figure files
that the externalize is to generate. Externalization works because it ask the
pgfplots to save the file into separate PDF first and include them in the final
output. Hence a separate stack and LaTeX process is launched for each figure.
A final note: It is extremely easy to blow up memory with pgfplots if making a
3D parametric plot. The reason is for a sample of \(N\), it expects for a
sample on variables x
and y
, hence a total of \(N^2\) sample points are
generated for each plot. If you did not use y
as a parameter, still \(N^2\)
sample points are generated. Therefore it is crucial to specify the y domain
in case no y
has used. Below is an example:
\begin{tikzpicture}
\begin{axis}[
xmin=-6,xmax=6,ymin=-6,ymax=6,zmin=-1,zmax=1,
view={20}{60},
grid,
samples=300
]
\addplot3[domain=-180:180, y domain=0:0, blue] (
{(4+sin(20*x))*cos(x)},
{(4+sin(20*x))*sin(x)},
{cos(20*x)}
);
\end{axis}
\end{tikzpicture}