2

I have the following macro that is invoked a lot (2871 for a document of 8 pages), because it is generated by a preprocessor:

\newcommand{\varid}[1]{\textbf{#1}}}

Using the profiler library of tikz, I figured out that this macro accounts for 2/3 of compile time, where another 1/6 is due to the preamble.

I also could pinpoint this to the use of the packages microtype and newtxmath, which are both included in acmart.

Here are a few observations:

  1. If I wrap \textbf for \mbox, performance is good.
  2. If I get rid of the dependency on either microtype or newtxmath, performance is good.
  3. Of course I can work around this problem; I just think it doesn't need to be so slow, as evident by (1) and (2). And it took me a lot of time to figure out what is wrong in the first place.

How can I speed up \textbf (I'm actually using \textsf{\textsl{#1}}, not that it makes a difference in performance)?

MWE:

\documentclass{article}

\usepackage{microtype}
\usepackage{newtxmath}

\usepackage{tikz}
\usetikzlibrary{profiler}

\newcommand{\varid}[1]{\textbf{#1}}
\pgfprofilenewforcommand{\varid}{1}

\begin{document}
\[\begin{array}{c}
\varid {$x$}\\
\varid {$x$}\\
\varid {$x$}\\
\varid {$x$}\\
\varid {$x$}\\
... repeat ad lib, I had about 700 lines ...
\end{array}\]
\end{document}

For me, this spends 2/3 of time in \varid:

...
Overfull \vbox (16549.99998pt too high) has occurred while \output is active [2]
pgflibraryprofiler: relative values are measured against the totaltime of `main job'.
 pgflibraryprofiler(main job) {total time=0.99443sec; (99.99847%) self time=0.084sec; (8.44574%) invocations=1; }
 pgflibraryprofiler(preamble) {total time=0.24377sec; (24.51324%) self time=0.24377sec; (24.51324%) invocations=1; }
 pgflibraryprofiler(<CS>varid) {total time=0.66666sec; (67.03796%) self time=0.66666sec; (67.03796%) invocations=696; }
(./mwe.aux)
...

Furthermore, according to \pgfprofilenewforcommand and piping the resulting log through tr '%.s', it appears that some calls take longer than others; up to 150ms per call.

What can I do about this? Is this a known interaction?

8
  • 1
    why are you using \text so often at all? And why do you switch in and out of mathmode like that? In your example I would only use \tau and \bm\tau. Dec 1, 2023 at 18:35
  • 1
    Well, not all my invokations are going into math mode like that; the majority in fact isn't. Besides; why would switching from math to text and into math be slower only if I include these particular packages? Dec 1, 2023 at 20:47
  • 1
    Basically because amsmath makes \text... macros work in sub- and superscripts. That's a lot of work.
    – campa
    Dec 1, 2023 at 20:51
  • @campa Aha, that's good to know. But does that mean it doesn't work outside amsmath? I removed \RequirePackage{microtype} from acmart.cls and I can't make out a meaningful difference. Here is a diff, for reference: draftable.com/compare/vUGXFHHKZYSR Dec 1, 2023 at 20:55
  • Try a_{\textrm{b}} with and without amsmarh and you'll see...
    – campa
    Dec 1, 2023 at 21:31

1 Answer 1

5

\varid {$ {\tau }$} will produce the same output as \tau but much slower. \text sets its argument 4 times in display, text, script and script script styles and for each of those it has to set up all the math fonts so even without microtype it's is going to be many times slower.

\tracingall length is a fairly good approximation to actual runtime comparison

if you do

\documentclass{article}
\usepackage{amsmath}
\begin{document}

\tracingall

$
\message{===}\tau\message{===}\text{$\tau$}\message{===}
$

\tracingnone

\end{document}

then between the first two === there is just 1 line

{\mathchar"11C}

Between the second two there are over 3 thousand lines

~.\text ->\protect \text  
{\relax}

~..\text  ->\ifmmode \expandafter \text@ \else \expandafter \mbox \fi 
{\ifmmode: (level 1) entered on line 8}
{true}
{\expandafter}
{\else: \ifmmode (level 1) entered on line 8}
{\fi: \ifmmode (level 1) entered on line 8}

~..\text@ #1->{\mathchoice {\textdef@ \displaystyle \f@size {#1}}{\textdef@ \te
xtstyle \f@size {\firstchoice@false #1}}{\textdef@ \textstyle \sf@size {\firstc
hoice@false #1}}{\textdef@ \textstyle \ssf@size {\firstchoice@false #1}}\check@
mathfonts }
#1<-$\tau $
{begin-group character {}
{entering math group (level 2) at line 8}
{\mathchoice}
{entering math choice group (level 3) at line 8}

~..\textdef@ #1#2#3->\hbox {{\everymath {#1}\let \f@size #2\selectfont #3}}
#1<-\displaystyle 
#2<-\f@size 
#3<-$\tau $

.....

~..\mv@bold@reset ->

As the end result of the two expressions are the same, simply removing all instances of
\text{$..$} or \textbf{$..$} will make things much faster.

10
  • See my updated Q, where I used \varid{$x$} instead of \varid{$\tau$}. Also note that wrapping \textbf{} in \mbox{} resolves the issue; I doubt that length of the trace would change much Dec 1, 2023 at 21:00
  • Well, actually the length of the diff changes much when I wrap it in an \mbox. Regardless; I don't see why I have to pay so much without so much as a warning Dec 1, 2023 at 21:04
  • \varid{$x$} is exactly the same as using \tau it produces the same as x but many times slower, \mbox changes things completely the trace would be just a few lines with \mbox{\textbf{$x}} @SebastianGraf "I doubt that length of the trace would change much " try it:-) Dec 1, 2023 at 21:45
  • 1
    \textbf{$x$} being the same as x is _by design` not a flaw, math does not pick up the current text font. so the fact that you are in a bold region does not change the math. @SebastianGraf Dec 1, 2023 at 21:49
  • 1
    @SebastianGraf it would be a bad trade to slow down processing for everyone just to check for a case that only happens for user error, there is no reason to ever use text in that way. Dec 4, 2023 at 15:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .