我知道以前也讨论过类似的问题(例如加速 LaTeX 编译),但这个问题更具体。
我想以编程方式创建一些报告,因此我编写了一个生成必要 TeX 文件的程序。该文件包含数百个 longtable 表(实际上是 longtabu)。编译时间不可接受(超过一分钟,报告可能会变得更大),我正在寻找减少它的方法。
总的来说,表格有 4 种类型。每种类型都有相同的标题行、相同的行数和相同的列数。唯一改变的是表格内的数据。是否可以加快编译时间?
如果有帮助的话,我知道每列的最大宽度(虽然 TeX 显然不知道)以及每种表格类型的行数。这类知识有用吗?
我还考虑过为每种表类型创建不同的 *.tex 文件,生成不同的进程进行编译,并将它们与 pdfpages 合并。有人用过这种技术吗,还是说这是浪费时间?
我已经预编译序言,但增益非常小。输出必须是 pdf。
编辑
我之所以关心性能是因为编译将在服务器端完成。
@Yiannis 以下是表格类型之一的 mwe。序言在所有表格中都很常见。我不使用现代计算机,但我认为字体选择在这种情况下并不重要。我并不真的需要标题在每一页上重复,尽管这样做会很好。再想想,对齐到小数点并不是真正必要的,但如果我不想让输出看起来不错,我就不会首先使用 LaTeX。
关于纯 TeX,您能提供一些指点吗?过去我只使用过 LaTeX。
@Bruno 非常感谢!您的解决方案非常快,但它不适用于 dcolumn,最重要的是间距非常糟糕。尝试复制您提供的表格,您会发现\bottomrule
第一个表格的 和\toprule
第二个表格的 之间根本没有空格。
\documentclass[a4paper,10pt,fleqn,final]{article}
\usepackage{xcolor}
\usepackage[a4paper,top=2cm,bottom=2cm,left=1.5cm,right=1.5cm]{geometry}
\usepackage{longtable, booktabs, multirow, tabu}
\usepackage{caption}
\usepackage{dcolumn}
\newcolumntype{d}[1]{D{.}{.}{#1}}
\newcommand{\mc}[1]{\multicolumn{1}{c}{#1}}
\newcommand{\mr}[1]{\multirow{2}{*}{#1}}
\begin{document}
\begin{longtabu}{cd{3.2}cd{3.2}cd{3.2}cd{3.2}cd{3.2}l}
\caption*{Synopsis of P75 - 97-558} \\
\toprule
\mc{\mr{LoadCase}} & \multicolumn{2}{c}{$N$} & \multicolumn{2}{c}{$V_{in}$} & \multicolumn{2}{c}{$V_{out}$} & \multicolumn{2}{c}{$M_{in}$} & \multicolumn{2}{c}{$M_{out}$} \\
\cmidrule(rl){2-3} \cmidrule(rl){4-5} \cmidrule(rl){6-7} \cmidrule(rl){8-9} \cmidrule(rl){10-11}
&\mc{UF} & State & \mc{UF} & State & \mc{UF} & State & \mc{UF} & State & \mc{UF} & State \\
\midrule
\endhead
\bottomrule
\endlastfoot
\midrule \multicolumn{11}{r}{{Continued on next page}} \\ \bottomrule
\endfoot
21 & 0.80 & Pass & 0.32 & Pass & 0.04 & Pass & 0.05 & Pass & 0.15 & Pass \\
22 & 0.76 & Pass & 0.02 & Pass & 0.03 & Pass & 0.09 & Pass & 0.11 & Pass \\
23 & 0.61 & Pass & 0.32 & Pass & 0.03 & Pass & 0.06 & Pass & 0.10 & Pass \\
24 & 0.56 & Pass & 0.02 & Pass & 0.02 & Pass & 0.06 & Pass & 0.07 & Pass \\
25 & 0.59 & Pass & 0.22 & Pass & 0.03 & Pass & 0.02 & Pass & 0.09 & Pass \\
26 & 0.56 & Pass & 0.02 & Pass & 0.02 & Pass & 0.06 & Pass & 0.07 & Pass \\
27 & 0.58 & Pass & 0.16 & Pass & 0.03 & Pass & 0.00 & Pass & 0.08 & Pass \\
28 & 0.56 & Pass & 0.02 & Pass & 0.02 & Pass & 0.06 & Pass & 0.07 & Pass \\
29 & 0.58 & Pass & 0.14 & Pass & 0.02 & Pass & 0.01 & Pass & 0.08 & Pass \\
30 & 0.56 & Pass & 0.02 & Pass & 0.02 & Pass & 0.06 & Pass & 0.07 & Pass \\
31 & 0.87 & Pass & 0.51 & Pass & 0.06 & Pass & 0.31 & Pass & 0.01 & Pass \\
32 & 0.64 & Pass & 0.31 & Pass & 0.07 & Pass & 0.13 & Pass & 0.03 & Pass \\
33 & 0.66 & Pass & 0.04 & Pass & 0.02 & Pass & 0.15 & Pass & 0.14 & Pass \\
34 & 0.85 & Pass & 0.78 & Pass & 0.01 & Pass & 0.29 & Pass & 0.15 & Pass \\
35 & 54.29 & \bfseries \color{red}Fail & 1.41 & \bfseries \color{red}Fail & 0.03 & Pass & 0.77 & Pass & 0.04 & Pass \\
36 & 6.89 & \bfseries \color{red}Fail & 1.21 & \bfseries \color{red}Fail & 0.00 & Pass & 0.72 & Pass & 0.08 & Pass \\
37 & 3.66 & \bfseries \color{red}Fail & 1.44 & \bfseries \color{red}Fail & 0.05 & Pass & 0.71 & Pass & 0.08 & Pass \\
38 & -1.00 & \bfseries \color{red}Fail & 1.62 & \bfseries \color{red}Fail & 0.02 & Pass & 0.75 & Pass & 0.12 & Pass
\end{longtabu}
\end{document}
答案1
如果您事先知道表格宽度,则可以“播种”LT 写入辅助文件的数据,以便它第一次就获得正确的宽度,这不会加快每次运行的速度,但意味着 LT 不需要多次运行即可收敛。(基本上查看 Lt 写入辅助文件的命令的格式,记录列宽,并将其放入文档序言中。)
如果增加 LTchunksize,编译速度可能会有所提高,根据现代 TeX 内存要求,您可能会将其增加很多,因此整个表将在一个块中处理。
如果您确实知道所有的宽度,并且不需要任何花哨的跨列行为,那么总是可以选择根本不使用 TeX 对齐方法,而只使每一行成为一行固定宽度的水平盒子。这节省了 TeX 将所有数据保存在未设置的框中并计算列宽的麻烦。
当然,所花费的时间取决于单元格的复杂程度,如果您摆脱了所有表格标记并将每个单元格设置为一个段落,那么这将不会提供您想要的布局,但会限制可实现的时间。
答案2
有很多方法可以优化编译速度,其中一种方法是在程序中直接使用 TeX,例如:
... code
\bye
无需加载大量开销(例如 pdfLaTeX 宏)。但是,下面的解决方案使用 pdfLaTeX,因为通过消除开销和写入文件,仍然可以使用 pdfLaTeX 获得令人满意的结果。这适用于计算机生成的数据,其中数据和输出的格式是预先知道的。我使用基本的 TeX 命令来定义宏和进行处理。我们逐行构建。MWE 在大约 6-7 秒内生成一个 11 页的表格(可以通过不加载连字符模式等、静音警告等来降低它)。MWE 示例使用第一个单元格的计数器来生成一些数据并跟踪输出的行数,并稍微减慢编译速度以模拟从磁盘读取数据。
\documentclass{article}
\usepackage[a4paper,top=2cm,bottom=2cm,left=1.5cm,right=1.5cm]{geometry}
\newcounter{ctr}
\begin{document}
\def\boxit#1{\hbox to 1cm{#1}}
\long\gdef\row{\hbox{\leavevmode\par \boxit{\thectr\stepcounter{ctr}} \boxit{0.85}
\boxit{Pass} \boxit{0.78}
\boxit{Pass}
\boxit{0.01}
\boxit{Pass}
\boxit{0.29}
\boxit{Pass}
\boxit{0.15}
\boxit{Pass}}\par}
\def\toprule{%
\hrule
\vskip5pt}
\def\bottomrule{\vskip5pt\hrule}
% save some typing
\long\def\many{\row\row\row\row\row\row\row\row\row\row\row\row\row\row
\row\row\row\row\row\row\row\row\row\row\row\row\row\row
\row\row\row\row\row\row\row\row\row\row\row\row\row\row
\row\row\row\row\row\row\row\row\row\row\row\row\row\row
\row\row\row\row\row\row\row\row\row\row\row\row\row\row
\row\row\row\row\row\row\row\row\row\row\row\row\row\row}
\long\def\manymore{\many\many\many\many\many\many\many
\many}
% the table
\toprule
\manymore
\bottomrule
\end{document}
由于时间限制,我没有包含标题(它需要像刺绣一样一块一块地缝制在一起,但并不难),但如果您遇到困难,请发表评论,我会稍后发布。标题也可以使用普通表格环境构建,因为它对编译的贡献不大。
答案3
另一个解决方案(我没有时间去实现)是向您的环境添加一个额外的选项。该选项取决于全局模式,可以设置为final
或draft
。
- 当全局模式时,
final
所有表都会被完全处理,无论额外的选项如何。 - 当全局模式为
draft
仅处理提供选项的表时。这对于您当前正在处理的(少数)表很有用。所有其他表环境只会忽略环境内的所有材料。
当全局模式为 时,此解决方案是最好的final
。当全局模式为 时,draft
它应该非常快,因为 LaTeX 只需排版目前正在开发的几个表格。
答案4
以下是基于 David Carlisle 提到的 Plain \hbox
stacking 的一些想法:
\newdimen\colwd \colwd=3em
\newbox\passbox \setbox\passbox\hbox to\colwd{Pass\hfil}
\newbox\failbox \setbox\failbox\hbox to\colwd{%
\special{color push rgb 1 0 0}Fail\special{color pop}\hfil}
\def\Pass{\copy\passbox}
\def\Fail{\copy\failbox}
\def\M#1 {\hbox to2\colwd{\hfil #1\hfil}}
\def\C#1 {\hbox to\colwd{\hfil #1\hfil}}
\def\L#1 {\hbox to\colwd{#1\hfil}}
\def\D#1.#2 {\hbox to\colwd{\hfil\llap{$#1$}.\rlap{$#2$}\hskip1.5em\hfil}}
\def\line#1{\hbox to\hsize{#1}}% just to show what they look like
\def\leftline#1{\line{#1\hfil}}
\leftline{\L \llap{Load}Case \M$N$ \M$V_{in}$ \M$V_{out}$ \M$M_{in}$ \M$M_{out}$ }
\leftline{\L{} \L UF \L State \L UF \L State \L UF \L State \L UF \L State \L UF \L State }
\medskip
\leftline{\L21 \D0.80 \Pass\D0.32 \Pass\D0.04 \Pass\D0.05 \Pass\D0.15 \Pass}
\leftline{\L22 \D0.76 \Pass\D0.02 \Pass\D0.03 \Pass\D0.09 \Pass\D0.11 \Pass}
\leftline{\L23 \D0.61 \Pass\D0.32 \Pass\D0.03 \Pass\D0.06 \Pass\D0.10 \Pass}
\smallskip
\leftline{\L24 \D0.56 \Pass\D0.02 \Pass\D0.02 \Pass\D0.06 \Pass\D0.07 \Pass}
\leftline{\L25 \D0.59 \Pass\D0.22 \Pass\D0.03 \Pass\D0.02 \Pass\D0.09 \Pass}
\leftline{\L26 \D0.56 \Pass\D0.02 \Pass\D0.02 \Pass\D0.06 \Pass\D0.07 \Pass}
\smallskip
\leftline{\L27 \D0.58 \Pass\D0.16 \Pass\D0.03 \Pass\D0.00 \Pass\D0.08 \Pass}
\leftline{\L28 \D0.56 \Pass\D0.02 \Pass\D0.02 \Pass\D0.06 \Pass\D0.07 \Pass}
\leftline{\L29 \D0.58 \Pass\D0.14 \Pass\D0.02 \Pass\D0.01 \Pass\D0.08 \Pass}
\smallskip
\leftline{\L30 \D0.56 \Pass\D0.02 \Pass\D0.02 \Pass\D0.06 \Pass\D0.07 \Pass}
\leftline{\L31 \D0.87 \Pass\D0.51 \Pass\D0.06 \Pass\D0.31 \Pass\D0.01 \Pass}
\leftline{\L32 \D0.64 \Pass\D0.31 \Pass\D0.07 \Pass\D0.13 \Pass\D0.03 \Pass}
\smallskip
\leftline{\L33 \D0.66 \Pass\D0.04 \Pass\D0.02 \Pass\D0.15 \Pass\D0.14 \Pass}
\leftline{\L34 \D0.85 \Pass\D0.78 \Pass\D0.01 \Pass\D0.29 \Pass\D0.15 \Pass}
\leftline{\L35 \D54.29 \Fail\D1.41 \Fail\D0.03 \Pass\D0.77 \Pass\D0.04 \Pass}
\smallskip
\leftline{\L36 \D6.89 \Fail\D1.21 \Fail\D0.00 \Pass\D0.72 \Pass\D0.08 \Pass}
\leftline{\L37 \D3.66 \Fail\D1.44 \Fail\D0.05 \Pass\D0.71 \Pass\D0.08 \Pass}
\leftline{\L38 \D-1.00 \Fail\D1.62 \Fail\D0.02 \Pass\D0.75 \Pass\D0.12 \Pass}
\bye
我使用了 XeTeX 的颜色\Fail
(我找不到它在 pdftex 中的工作原理)。我还使用了空格而不是规则,因为我发现这种方式更好。您还可以将“标题”行保存在一个框中。我有点怀疑这种方式是否真的比 更快\halign
。