Another solution.
Decompress the format file in advance
Technically this method relies on internal implementation details of the engines, but it works anyway.
You can do the following. Assuming the file to be compiled is helloworld.tex
.
gunzip < "$(kpsewhich -engine=luahbtex lualatex.fmt)" > lualatexunzipped.fmt
lualatex '&lualatexunzipped' helloworld.tex
The first command should be done once, and keep the resulting generated lualatexunzipped.fmt
file in the same directory as the TeX file (or somewhere that is pointed to by kpsewhich -var-value=TEXFORMATS
).
Then, the second command should be used to compile a file instead of the usual lualatex helloworld.tex
.
Speed up:
$ time lualatex helloworld.tex
real 0m0.775s
user 0m0.546s
sys 0m0.215s
$ cp "$(kpsewhich -engine=luahbtex lualatex.fmt)" lualatexa.fmt
$ time lualatex '&lualatexa' helloworld.tex
real 0m0.642s
user 0m0.490s
sys 0m0.145s
$ time lualatex '&lualatexunzipped' helloworld.tex
real 0m0.543s
user 0m0.382s
sys 0m0.155s
Note that if the format file name is lualatex
then apparently kpathsea
will be invoked to search something, which takes another approximately 0.1 seconds.
Thus, copying the format file to ./lualatexa.fmt
alone (without decompression) already save 0.1s.
You can save ≈ 0.1 to 0.2 seconds per compilation this way. Significant if your file is small.
Explanation
First, read my answer on precompiled preamble to understand what .fmt
format files are.
Then, roughly speaking, this is because the implementation of the TeX engines use the gzip format for the .fmt
files, and gzdopen
function is used to read the file. However, it has a compression level 0 which states that the input is the same as the output.
As long as the decompressed file is not a valid gzip archive (and that gzdopen
does not complain when the level being passed in is different from the level of the actual archive), everything should be fine.
Note 2
If the decompressed file happens to be a valid gzip archive (perhaps because it starts with the magic number 1f 8b
?) then
you might be able to use the following to compress it at level 0:
python -c 'import sys, gzip; sys.stdout.buffer.write(gzip.compress(sys.stdin.buffer.read(), compresslevel=0))' < lualatexunzipped.fmt > lualatexzipped0.fmt
My version of gzip
does not accept -0
as input, although it accepts -1
until -9
.
Note
Unsurprisingly, this will bloat the format file size.
From LuaTeX source code:
/*tex
Tests has shown that a level 3 compression is the most optimal tradeoff
between file size and load time.
*/
#define COMPRESSION "R3"
For other engines
gunzip < "$(kpsewhich -engine=xetex xelatex.fmt)" > xelatexunzipped.fmt
xelatex '&xelatexunzipped' helloworld.tex
gunzip < "$(kpsewhich -engine=pdftex pdflatex.fmt)" > pdflatexunzipped.fmt
pdflatex '&pdflatexunzipped' helloworld.tex
Combine this solution with precompiled preamble
Similarly, this solution can be combined with precompiled preamble for even more speedup.
Dangerous: modify the user format files
NOTE: If you do this, you'll need to delete the local format files and re-create them for every TeX update.
Do the following.
mktexfmt pdflatex
pdflatex_fmt="$(kpsewhich -engine=pdftex pdflatex.fmt)"
mv "$pdflatex_fmt" "$pdflatex_fmt".gz
gunzip "$pdflatex_fmt".gz
mktexfmt xelatex
xelatex_fmt="$(kpsewhich -engine=xetex xelatex.fmt)"
mv "$xelatex_fmt" "$xelatex_fmt".gz
gunzip "$xelatex_fmt".gz
mktexfmt lualatex
lualatex_fmt="$(kpsewhich -engine=luahbtex lualatex.fmt)"
mv "$lualatex_fmt" "$lualatex_fmt".gz
gunzip "$lualatex_fmt".gz
In each block, the first command creates a per-user format file.
Read the warning.
*************************************************************
* *
* WARNING: you are switching to fmtutil's per-user formats. *
* Please read the following warnings! *
* *
*************************************************************
You have run fmtutil-user (as opposed to fmtutil-sys) for the first time;
this has created format files which are local to your personal account.
From now on, any changes in system formats will *not* be automatically
reflected in your files; furthermore, running fmtutil-sys will no longer
have any effect for you.
As a consequence, you yourself have to rerun fmtutil-user after any
change in the system directories. For example, when one of the LaTeX or
other format source files changes, which happens frequently.
See https://tug.org/texlive/scripts-sys-user.html for details.
If you want to undo this, remove the files mentioned above.
The remaining 3 commands just decompress that file.
Note, however, that this solution is slightly slower than the solution above because of kpathsea path search for something.
References
texdoc pdftex
documents the usage of TEXFORMATS
and other Web2c variables.
file.fmt
, so that subsequent compilations can quickly read in that file and start from there instead of going through all of thenewdefs
(tex.stackexchange.com/q/79493/107497 and many links therein).