I've tried a small benchmark and it seems that concatenation with .. is a bit faster than repeated tex.print. Note that it is a very simple benchmark and the performance might change if there are other factors involved, for example if the concatenated string becomes very long the typesetting may be more complicated than a sequence of shorter strings (with line breaks/hyphenation, paragraph layout etc).
First a benchmark with time lualatex testfile.tex (Linux), which computes the time for the full process. The code below concatenates 10 strings, of which one is a random number to prevent caching, either with the .. operator or with repeated tex.print calls. This is repeated 50,000 times, which generates 1087 pages of output.
\documentclass{article}
\usepackage{luacode}
\begin{luacode*}
function dotconcat()
a = "abc "
c = "def "
d = "ghi "
e = "\\par"
for i=1,50000 do
b = math.random(1000)
x = a .. b .. c .. d .. a .. b .. c .. d .. a .. b .. e
tex.print(x)
end
end
function texprintconcat()
a = "abc "
c = "def "
d = "ghi "
e = "\\par"
for i=1,50000 do
b = math.random(1000)
tex.print(a) tex.print(b)
tex.print(c) tex.print(d)
tex.print(a) tex.print(b)
tex.print(c) tex.print(d)
tex.print(a) tex.print(b)
tex.print(e)
end
end
\end{luacode*}
\begin{document}
% either
\directlua{dotconcat()}
% or
%\directlua{texprintconcat()}
\end{document}
Timing results with dotconcat():
real 0m6,548s
user 0m6,435s
sys 0m0,108s
With texprintconcat():
real 0m7,016s
user 0m6,890s
sys 0m0,120s
Second benchmark with l3benchmark, which measures only the time used in the function call:
\documentclass{article}
\usepackage{luacode}
\usepackage{l3benchmark}
\begin{luacode*}
function dotconcat()
a = "abc "
c = "def "
d = "ghi "
e = "\\par"
b = math.random(1000)
x = a .. b .. c .. d .. a .. b .. c .. d .. a .. b .. e
tex.print(x)
end
function texprintconcat()
a = "abc "
c = "def "
d = "ghi "
e = "\\par"
b = math.random(1000)
tex.print(a) tex.print(b)
tex.print(c) tex.print(d)
tex.print(a) tex.print(b)
tex.print(c) tex.print(d)
tex.print(a) tex.print(b)
tex.print(e)
end
\end{luacode*}
\begin{document}
\ExplSyntaxOn
\benchmark_once:n{%
\prg_replicate:nn {50000} {\directlua{dotconcat()}}% or texprintconcat()
}
\ExplSyntaxOff
\end{document}
Results:
dotconcat()
7.98 seconds (3.03e7 ops)
texprintconcat()
8.16 seconds (2.61e7 ops)
Note that the benchmark itself adds another 1 second to the compilation. The difference is between 200ms (l3benchmark) and 400ms (Linux time), which is a few percent of the total - so not fully negligible but also not very substantial.
Edit: to simplify the benchmark code I used \benchmark_once:n{\directlua{dotconcat()}} (and the same for texprintconcat()) on the code with the for loop, which amplifies the results:
dotconcat: 8.93 seconds (2.84e7 ops)
texprintconcat: 9.9 seconds (2.8e7 ops)
Even though the number of operations is now more equal, the time taken for tex.print is now 1 second more than the .. case. This shows once more that benchmarking is tricky, and you should be careful when interpreting the results.