我想对我加载的软件包(其中一些是我自己编写的)实现自动基准测试。目前我的前言部分需要 15 秒才能加载,比编译文档其余部分所需的时间要长得多。
为此,我想实现这一点回答,建议使用etoolbox
来patchcmmd
修补usepackage
。由于我的大部分软件包加载都发生在我自己的软件包内部,所以我想在 上使用这种方法RequirePackage
。然而,我选择使用xpatch
的实用程序,因为我读到过,常规patchcmd
无法处理带有可选参数的命令。
到目前为止我最好的尝试是这样的(请不要介意通过 AfterEndPreamble 的丑陋的自动输出):
\RequirePackage{fp}
\RequirePackage{xpatch}
\newcount\timer
\xpretocmd{\RequirePackage}{\pdfresettimer}{}{}
\xapptocmd{\RequirePackage}{
\timer=\pdfelapsedtime
\FPdiv\temp{\the\timer}{65.536}
\FPtrunc\temp\temp{3}
\AfterEndPreamble{\par{#1:} \temp}
}{}{}
% Testing
\RequirePackage{tikz}
\RequirePackage{mathtools}
\documentclass{article}
\begin{document}
\end{document}
但不幸的是,这会产生一个错误:
! LaTeX Error: File `\timer.sty' not found.
我最好的猜测是,这是因为ProvideCommand
在正常参数之后有第二个可选参数,并且xpatchcmd
无法处理它,导致使用附加的文本作为其主要参数。但是我在这里已经远远超出了我的舒适区,到目前为止ProvideCommand
我还没有设法理解它(并且我认为无论如何一定有更好的方法,只需用周围的代码修补命令,而无需了解其内部结构)。任何帮助都非常感谢。ProvideCommand
\show
答案1
收益latexdef RequirePackage
率
% latex.ltx, line 10034:
\def\RequirePackage{%
\@fileswithoptions\@pkgextension}
哦,好吧,现在我们需要做的latexdef @fileswithoptions
% latex.ltx, line 10097:
\def\@fileswithoptions#1{%
\@ifnextchar[%]
{\@fileswith@ptions#1}%
{\@fileswith@ptions#1[]}}
这意味着宏吸收一个标记或一个括号参数并测试是否[
出现 a。如果你在 的末尾添加这些标记\RequirePackage
,则传递给 的参数\@fileswithoptions
将是\@pkgextension
,而 的测试[
将返回 false,因此我们最终会得到
\@fileswith@ptions\@pkgextension\timer=\pdfelapsedtime
正如你所见,这将失败,因为
\def\@fileswith@ptions#1[#2]#3{%
\@ifnextchar[%]
{\@fileswith@pti@ns#1[{#2}]#3}%
{\@fileswith@pti@ns#1[{#2}]#3[]}}
所以参数#3
将\timer
代替文件名列表(不带扩展名)。
\RequirePackage
抱歉,但由于您加载的包嵌套,这不会以任何合理的方式起作用。
\RequirePackage{fp}
\newcount\timer
\newcommand{\TimeRequirePackage}[1]{%
\pdfresettimer
\RequirePackage{#1}%
\timer=\pdfelapsedtime
\FPdiv\temp{\the\timer}{65.536}%
\FPtrunc\temp\temp{3}%
\printresult{#1}%
}
\newcommand{\printresult}[1]{\expandafter\printresultaux\expandafter{\temp}{#1}}
\newcommand{\printresultaux}[2]{\AtBeginDocument{\par#2: #1}}
% Testing
\TimeRequirePackage{tikz}
\TimeRequirePackage{mathtools}
\documentclass{article}
\begin{document}
\end{document}
\temp
请注意,在将其传递给\AtBeginDocument
(不是)之前,需要进行扩展\AtEndPreamble
。
和xfp
\RequirePackage{xfp}
\newcommand{\TimeRequirePackage}[1]{%
\pdfresettimer
\RequirePackage{#1}%
\expanded{\noexpand\AtBeginDocument{\par#1: \fpeval{round(\pdfelapsedtime/65.536,3)}}}
}
% Testing
\TimeRequirePackage{tikz}
\TimeRequirePackage{mathtools}
\documentclass{article}
\begin{document}
\end{document}
答案2
您可以使用(使用新的 latex)包钩子来定义应该测量的包列表(计算是从 egregs 答案中窃取的):
\ExplSyntaxOn
\newcommand{\BenchmarkPackages}[1]
{%
\clist_map_inline:nn{#1}
{
\AddToHook{package/before/##1}{\pdfresettimer}
\AddToHook{package/after/##1}{\typeout{##1: \fp_eval:n{round(\pdfelapsedtime/65.536,3)}}}
}
}
\ExplSyntaxOff
\BenchmarkPackages{tikz,mathtools,scrbase}
\documentclass{scrartcl}
\usepackage{tikz}
\begin{document}
alblb
\end{document}
然后会在日志中写入类似 tikz:1085.999 的内容(当然也可以存储该值并在稍后打印)。