在 pdfTeX 中,该\pdfelapsedtime
原语允许访问自此 pdfTeX 运行开始以来的时间,以“缩放秒数”(1/65536 秒)为单位。这对于对代码进行基准测试很有用:重复多次,并测试其所用的时间。
\newcount\benchmarkcount
\long\def\tenfold#1{#1#1#1#1#1#1#1#1#1#1}
\long\edef\thousandfold{\tenfold{\tenfold{\tenfold{#1}}}}
\long\def\benchmark#1{%
\benchmarkcount\pdfelapsedtime
\thousandfold{#1}%
\typeout{\the\dimexpr\pdfelapsedtime sp-\benchmarkcount sp miliseconds}%
}
是否有可能在 XeTeX 和/或 LuaTeX 中以类似的方式访问时间?
答案1
在这里,以下代码看起来与原始原语非常接近。我们首先查看 pdflatex 发行说明(2005-08-01)
\pdfelapsedtime
是一个只读整数,它(最初)返回自本次运行开始以来经过的时间量。该量以“缩放秒数”给出:值 65536 计为一秒。如果经过的时间超过 32767 秒,则将返回 (2^31)-1。\pdfresettimer
更新内部计时器,以便后续调用\pdfelapsedtime
将从 0 重新开始。
现在,尝试在用户空间重新实现:
\directlua{pdfelapsedtimer_basetime=0}
os.clock()
从 lua 的开头开始计数,因此pdfelapsedtimer_basetime
设置为零。无需读取初始os.clock()
值,反正它应该是 0。来自 lua.org:
os.clock 函数返回程序的 CPU 时间(秒数)。它的典型用途是对一段代码进行基准测试
如果用户想要重置它,pdflatex 原语是\pdfresettimer
。在这种情况下,我们读出os.clock()
并将其存储在 中,pdfelapsedtimer_basetime
以便稍后减去偏移量。
\protected\def\pdfresettimer{\directlua{pdfelapsedtimer_basetime = os.clock()}}
最后,\pdfelapsedtime
宏减去偏移量得到秒数,乘以 65536 得到缩放后的秒数,加上 0.5 以使函数math.floor
正确舍入并返回一个整数。我们需要一个整数,而不是标记流中的字符,因此,\numexpr
被利用。
\protected\def\pdfelapsedtime{\numexpr\directlua{tex.print(math.floor((os.clock()-pdfelapsedtimer_basetime)*65536+0.5))}\relax}
以下 MWE 是针对原始问题的实现:
\documentclass{article}
\newcount\benchmarkcount
\long\def\tenfold#1{#1#1#1#1#1#1#1#1#1#1}
\long\edef\thousandfold#1{\tenfold{\tenfold{\tenfold{#1}}}}
\long\def\benchmark#1{%
\benchmarkcount\pdfelapsedtime
\thousandfold{#1}%
\typeout{\the\dimexpr\pdfelapsedtime sp-\benchmarkcount sp}%
}
\usepackage{lipsum}
\directlua{pdfelapsedtimer_basetime=0}
\protected\def\pdfresettimer{\directlua{pdfelapsedtimer_basetime = os.clock()}}
\protected\def\pdfelapsedtime{\numexpr\directlua{tex.print(math.floor((os.clock()-pdfelapsedtimer_basetime)*65536+0.5))}\relax}
\begin{document}
\benchmark{\lipsum}
\end{document}