Skip to content
  • Sponsor matplotlib/matplotlib

  • Notifications You must be signed in to change notification settings
  • Fork 7.9k

LaTeX rendering is really slow #4880

Closed as not planned
Closed as not planned
@lgeiger

Description

@lgeiger

When usetex=True plotting is a lot slower than the normal.

I generated a simple testplot with some mathtex and timed the rendering time with usetex=True and usetex=False for both saving the plot and just displaying it:

import matplotlib.pyplot as plt
import matplotlib
import numpy as np
%matplotlib inline
x = np.linspace(0, 20, 500)
y = 3 * x + 0.5 * x**3 + 2

def plot(x, y):
    plt.plot(x, y)
    plt.title('simple testplot')
    plt.xlabel('$x$')
    plt.ylabel(r'$3 x + \frac{1}{2} x^3 + 2$')
    plt.savefig('test.pdf')

%timeit -n 1 -r 1 plot(x, y)

Here are the measurements:

  • save pdf usetex=False: 351 ms
  • save pdf usetex=True: 8.34 s
  • display usetex=False: 39 ms
  • display usetex=True: 38.3 ms but it took approx. 7 s until the plot was displayed

My system is running Mac OS X 10.10.4, matplotlib 1.4.3 and the latest LaTeX version.

Activity

tacaswell

tacaswell commented on Aug 7, 2015

@tacaswell
Member

Is it any faster the second time? I suspect much of that delay is because with usetex a new LaTeX process is being spun up, the text processed and rendered, converted to png, and then added back into the figure.

That said, 8s is pretty crazy. I use usetex day-to-day and have never seen anything that bad.

Does in work better not in the notebook and using one of the backends that we support?

lgeiger

lgeiger commented on Aug 7, 2015

@lgeiger
Author

Yes caching works.
It takes about 2 s for saving the same plot a second time. But if something in the plot is changed rendering times are again 4-5 s even if the plot is not displayed.

Just displaying a plot the second time works ok. If anything is modified it takes again 3-5s till the plot is displayed.
The problem exists with other backends or outside of the notebook as well.

pwuertz

pwuertz commented on Aug 10, 2015

@pwuertz
Contributor

Order of seconds is what I'd consider pretty normal whenever latex is involved somewhere.

jkseppan

jkseppan commented on Sep 19, 2015

@jkseppan
Member

TeX gets run separately for each string in the image, including every tick label. One optimisation would be to first gather all the TeX input, then make a big TeX file where each string is on its own page, then turn each output page into a separate png file (or a separate sequence of rendering commands in the case of vector backends).

jkseppan

jkseppan commented on Sep 19, 2015

@jkseppan
Member

One workaround: if you don't need everything to be rendered with TeX, you can set the usetex property on a subset of text objects.

import matplotlib.pyplot as plt
import matplotlib
matplotlib.rc('text', usetex=False)
import numpy as np
%matplotlib inline
x = np.linspace(0, 20, 500)
y = 3 * x + 0.5 * x**3 + 2

def plot(x, y):
    plt.plot(x, y)
    plt.title('simple testplot')
    plt.xlabel('$x$', usetex=True)
    plt.ylabel(r'$3 x + \frac{1}{2} x^3 + 2$', usetex=True)
    plt.savefig('test.pdf')

%timeit -n 1 -r 1 plot(x, y)
tdegeus

tdegeus commented on Oct 10, 2017

@tdegeus

Same here. I also must add that on macOS it is significantly slower than on for example Linux. What could be the reason for this?

entaylor

entaylor commented on Jan 5, 2018

@entaylor

This is only to bump this as a serious issue on MacOS (having just upgraded to High Sierra, python 3.6, and matplotlib 2.1.1). Depending on the plot, rendering with TeX can take minutes.

For a simple plot with x and y axis labels and just a '$m = 2.2 \pm 1.1$' annotation, the save time is 26 seconds. Yes, caching works, so that subsequent re-saves of the same plot take closer to 1 second. But if i, for example, change the annotation to have a different number of decimal places, then we are back to 8.8 sec.

jkseppan's workaround with usetex=True only for the x/y labels and annotation does not significantly reduce the save time: it's 8.4 sec instead of 8.8 sec.

anntzer

anntzer commented on Jan 5, 2018

@anntzer
Contributor

Just a data point here:
Looks like a significant (less than half, though) part of the time is spent calling not tex, but kpsewhich (which is done by dviread to locate font files).
Possible relevant threads: https://email.esm.psu.edu/pipermail/macosx-tex/2014-October/053020.html https://tug.org/pipermail/tex-k/2015-April/002600.html

I have a longish-term plan to hack into usetex to let the tex subprocess output directly as much relevant information as possible into the log file (with some tex programming)...

jkseppan

jkseppan commented on Jan 5, 2018

@jkseppan
Member
anntzer

anntzer commented on Jan 5, 2018

@anntzer
Contributor

kpathsea is actually LGPL so we're fine (but I have no idea whether that'll help)

tdegeus

tdegeus commented on Jan 5, 2018

@tdegeus

Possible duplicate: #9653

jkseppan

jkseppan commented on Jan 6, 2018

@jkseppan
Member

So I was guessing that the invocation of kpsewhich is the slow part, but I haven't measured it. It could also be that the way it searches the file system is slower on a Mac than on Linux. If that's the case, then linking to kpathsea wouldn't buy anything.

It would be useful to measure what's actually happening on a Mac. I thought the tool of choice for this would be DTrace but apparently that has been broken for several OS versions. Does anyone know how to trace subprocesses and their system calls on macOS?

anntzer

anntzer commented on Jan 6, 2018

@anntzer
Contributor

I just used

  1. a python profiler (pprofile, but there's a bunch of them that would probably work) to see that one of the bottlenecks is the calls to kpsewhich, and
  2. the time shell builtin to time the calls to kpsewhich cmr10.pfb pdftex.map, which is about 5x slower on OSX (0.11s) than on linux (0.2s) (arguably different machines though). Interestingly the duration of the call is essentially independent of the number of files searched, so it is some "initialization" step that is slower.

Apparently kpsewhich has an "-interactive" mode, which may be a way to bypass that initialization (but would require writing our own loop to manage the subprocess' stdout -- a bit a pain but not that hard, see handling of inkscape for testing).

jkseppan

jkseppan commented on Jan 6, 2018

@jkseppan
Member

Could someone who is experiencing slow TeX rendering try out branch jkseppan:kpsewhich-batching and report back whether it's noticeably faster?

28 remaining items

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      LaTeX rendering is really slow · Issue #4880 · matplotlib/matplotlib