Comparing the speed of Metapost and TikZ
Posted on October 10, 2018
As a frequent user of both Metapost and TikZ, I often observe that TikZ is considerably slower than Metapost. But what’s the actual difference in speed? Let’s consider basic operations: drawing straight lines and drawing circles.
\usemodule[tikz]
\starttext
\testfeatureonce{1000}
{\setbox0\hbox
{\startMPcode draw (0,0) -- (1cm, 1cm); \stopMPcode}}
\elapsedtime
\testfeatureonce{1000}
{\setbox0\hbox
{\starttikzpicture \draw (0,0) -- (1cm, 1cm); \stoptikzpicture}}
\elapsedtime
\testfeatureonce{1000}
{\setbox0\hbox
{\startMPcode draw fullcircle scaled 1cm; \stopMPcode}}
\elapsedtime
\testfeatureonce{1000}
{\setbox0\hbox
{\starttikzpicture \draw (0,0) circle (1cm); \stoptikzpicture}}
\elapsedtime
\stoptext
The function \testfeatureonce{n}{...}
runs the code inside the second
argument n
times and stores the elapsed time in the macro \elapsedtime
.
So, in the above example, we are drawing a straight line (or a circle) 1000
times, saving the output to a box (so that we don’t include the overhead of
writing the content to PDF), and measuring the elapsed time. The result is as
follows (formatted for clarity).
Shape | Metapost | TikZ |
---|---|---|
Line | 0.434s | 1.239s |
Circle | 0.533s | 1.597s |
So, TikZ is almost 3 times slower than Metapost for basic shapes.
Now, let’s try something more complicated: drawing a 2 state Markov chain. One of the selling features of TikZ is that drawing more “complicated” graphics is easy. Here is the code for drawing such a chain in TikZ:
\usemodule[tikz]
\usetikzlibrary[positioning]
\starttext
\tikzset{state/.style={circle, draw,
line width=2bp,
inner sep=0.5em,
draw=blue!85,
fill=blue!25!white,
}}
\starttikzpicture[line width=1bp]
\node[state] (off) {$0$};
\node[state, right=of off] (on) {$1$};
\draw[every loop]
(off) edge[bend right, auto=right] node {$p$} (on)
(on) edge[bend right, auto=right] node {$q$} (off)
(off) edge[loop left] node {$1-p$} (off)
(on) edge[loop right] node {$1-q$} (off)
;
\stoptikzpicture
\stoptext
Using \testfeatureonce{100}{...}
on this code takes 4.278s on my laptop.
So, drawing one Markov chain takes about 43ms.
Metapost is a more declarative language, so Metapost code is more elaborate. Here is one way to draw the same figure in Metapost:
\startMPinclusions
input boxes;
\stopMPinclusions
\starttext
\startMPcode
pickup pencircle scaled 1bp;
circleit.Off("$0$");
circleit.On ("$1$");
circmargin := 1EmWidth;
Off.c = origin;
On.w - Off.e = (1cm, 0);
forsuffixes Box=Off, On :
fill bpath Box withcolor 0.75[blue,white];
drawunboxed(Box);
draw bpath Box withcolor 0.8blue withpen pencircle scaled 2bp;
endfor
newpath p, q;
p := Off.c {dir -40} .. On.c
cutbefore bpath Off
cutafter bpath On
cutends (0,1mm);
q:= On.c {dir 140} .. Off.c
cutbefore bpath On
cutafter bpath Off
cutends (0,1mm);
drawarrow p;
drawarrow q;
label.bot ("$p$", point 0.5 along p);
label.top ("$q$", point 0.5 along q);
p := Off.c {dir 150} .. (Off.w - (0.75cm, 0)) .. {dir 30} Off.c
cutbefore bpath Off
cutafter bpath Off
cutends (0,1mm);
q := On.c {dir -30} .. (On.e + (0.75cm, 0)) .. {dir -150} On.c
cutbefore bpath On
cutafter bpath On
cutends (0,1mm);
drawarrow;
drawarrow;
label.lft("$1-p$", point 0.5 along p);
label.rt ("$1-q$", point 0.5 along q);
\stopMPcode
\stoptext
This code could have been made somewhat terser by defining macros Edge
and
Loop
but I am not doing so. Running \testfeatureonce{100}{...}
on the
above code takes 0.790s on my laptop. So drawing one Markov chain takes
about 8ms. For a somewhat more complicated drawing, TikZ is almost 5
times slower than Metapost.
But the speed tradeoff comes at a cost. The TikZ code is terser than Metapost and hides some of the complexity behind convenience macros. So, it is easier to understand (at least for beginners). This also explains why TikZ is so much more popular than Metapost. But the speed advantage makes me wonder: would there be significant speedup in TikZ code if Lua is used for parsing the input and metapost is used for drawing. In other words, is it worthwhile to rewrite the PGF backend for LuaTeX?
This entry was posted in Metapost and tagged metapost, tikz, efficiency.