简体   繁体   中英

Bokeh's export_png function is very slow

I have a very simple Python script (which essentially executed instantaneous, except the very last line):

  from bokeh.plotting import figure
  from bokeh.io import export_png

  x_labels = ['AAA','BBB','CCC']
  y_values = [5,7,2]
  p = figure(title='test', x_range=x_labels, plot_height=300, plot_width=500)
  c = p.vbar(x=x_labels, top=y_values, width=0.15, line_color=None)

  export_png(p, filename=r'C:\MyImage.png')  #  <--- takes very long

The last line with export_png takes ~5-10 seconds. Re-running the last line alone is quicker a second time round (~1-2 seconds). So seemingly it "warms up". But is there anything I can do to speed this up, or this is a known "feature"?


I tried this on all recent bokeh versions (1.0.2, 1.2.0, 1.4.0), but all yield the same result. My PhantomJS is on version 2.1.1 and its path os.environ.get('BOKEH_PHANTOMJS_PATH') is set to C:\\\\Users\\\\USERNAME\\\\AppData\\\\Roaming\\\\npm\\\\node_modules\\\\phantomjs-prebuilt\\\\lib\\\\phantom\\\\bin\\\\phantomjs.exe as required.

Bokeh is a browser-based plotting tool, so in order to export to PNG, it has to:

  • start an external webdriver process for a headless browser (PhantomJS, by default)
  • serialize and send the JSON representation of the Bokeh content to that process
  • have the headless browser process:
    • render all the Bokeh content
    • capture a screenshot using webdriver APIs
    • send the image data back to the Python process

There is some overhead to creating the webdriver process, which is why Bokeh caches a webdriver instance on first use, by default. That is why the first export takes longer, and subsequent exports are faster. But there's not really any room here to make improvements. About the only thing that is "adjustable" and might change things is the choice of webdriver, eg you could try with Chromedriver or Geckodriver. (In fact there is on open PR to switch to Geckodriver as a default since PhantomJS is deprecated and no longer maintained.) However, it's not certain to me that either of those is actually faster than PhantomJS.

All that said, I have not personally experienced 10 seconds even for a first render. As a reference, the code above takes ~1.7 seconds for a first render and 300ms for a later render, on a fairly old Macbook:

In [8]: %time export_png(p, filename=r'C:\MyImage.png')
CPU times: user 107 ms, sys: 38.7 ms, total: 146 ms
Wall time: 1.69 s

In [9]: %time export_png(p, filename=r'C:\MyImage.png')
CPU times: user 74.6 ms, sys: 9.2 ms, total: 83.8 ms
Wall time: 319 ms
Out[9]: '/Users/bryan/tmp/C:\\MyImage.png'

I suppose there could be a platform difference, perhaps the overhead to start a process is higher on Windows? Another avenue you could look in to is to make sure your Selenium package is up to date, it's possible that they might have made improvements in some way and that updating it would help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM