散景:在jupyter实验室重复绘制会增加(浏览器)的内存使用量 - python

我正在使用Bokeh在Jupyter实验室笔记本中绘制许多时间序列(> 100)和许多点(〜20,000)。
在Jupyter中多次执行单元时,每次运行时Chrome的内存消耗将增加400mb以上。在执行了几次单元操作后,Chrome往往会崩溃,通常是在累积了几GB RAM使用量的情况下。此外,每次执行后,绘图趋向于变慢。

Jupyter中的“清除[所有]输出”或“重新启动内核并清除所有输出...”也不会释放任何内存。在经典的Jupyter Notebook以及Firefox或Edge中,也会出现此问题。

我的.ipynp的最低版本:

import numpy as np
from bokeh.io import show, output_notebook
from bokeh.plotting import figure
import bokeh
output_notebook() # See e.g.: https://github.com/bokeh/bokeh-notebooks/blob/master/tutorial/01%20-%20Basic%20Plotting.ipynb
# Just create a list of numpy arrays with random-walks as dataset
ts_length = 20000
n_lines = 100
np.random.seed(0)
dataset = [np.cumsum(np.random.randn(ts_length)) + i*100 for i in range(n_lines)]
# Plot exactly the same linechart every time
plot = figure(x_axis_type="linear")
for data in dataset:
    plot.line(x=range(ts_length), y=data)
show(plot)

即使我每次在重新执行上面的(绘图)单元之前每次都执行以下单元格,这种“内存泄漏”行为仍会继续:

bokeh.io.curdoc().clear()  
bokeh.io.state.State().reset()
bokeh.io.reset_output()

output_notebook() # has to be done again because output was reset

Bokeh中是否还有其他可能被我忽略的机制,可以使我清理情节并释放内存(在browser / js / client中)?

为了避免此问题,我是否必须在Jupyter Notebook中以其他方式绘制(或显示绘制)图?还是这仅仅是Bokeh / Jupyter的错误?

我的系统上的已安装版本(Windows 10):

Python 3.6.6:Anaconda自定义(64位)
散景:1.4.0
铬:78.0.3904.108
jupyter:

核心:4.6.1
实验室:1.1.4
ipywidgets:7.5.1
labextensions:

@ bokeh / jupyter_bokeh:1.1.1版
@ jupyter-widgets / jupyterlab-manager:v1.0。*

参考方案

TLDR;这可能值得making an issue(s) for。

内存使用情况

关于不同方面的一些注意事项:

清除/重置功能

首先要注意的是:

bokeh.io.curdoc().clear()  
bokeh.io.state.State().reset()
bokeh.io.reset_output()

仅影响Python进程中的数据结构(例如Jupyter Kernel)。它们永远不会对浏览器的内存使用或占用空间产生任何影响。

一次性内存占用

仅基于数据,我希望大约在64MB附近:

20000 * 100 * 2 * 2  * 8 = 64MB

那就是:100行带有20k(x,y)点,这也将转换为(sx,sy)屏幕坐标,所有这些都以float64(8字节)类型数组表示。但是,Bokeh还会为所有数据构造一个空间索引,以支持诸如悬停工具之类的功能。我希望您正在用此数据炸毁该索引。可能值得将该功能进行配置,以便不需要命中测试的人不必为此付费。讨论此问题的功能请求问题将是适当的。

重复执行

应该有DOM事件触发器,这些触发器将在重新执行笔记本单元时清除。也许这些已经坏了?不幸的是,与一个很小的团队保持三种大型混合Python / JS工具(包括经典Notebook)之间的集成是一个持续的挑战。错误报告问题将是适当的,以便可以对其进行跟踪和调查。

其他选择

您现在能做什么?

更佳的用法

至少对于特定情况,您的时间序列都具有相同的长度,上面的代码以非常次优的方式构造。您应该尝试将所有内容放在单个ColumnDataSource中:

ts_length = 20000
n_lines = 100
np.random.seed(0)

source = ColumnDataSource(data=dict(x=np.arange(ts_length)))
for i in range(n_lines):
    source.data[f"y{i}"] = np.cumsum(np.random.randn(ts_length)) + i*100

plot = figure()
for i in range(n_lines):
    plot.line(x='x', y=f"y{i}", source=source)
show(plot)

通过将序列文字传递给line,您的代码将导致创建99个不必要的CDS对象(每个line调用一个)。也不会重新使用x数据,从而导致不必要地向BokehJS发送99 * 20k的额外点。并且通过发送普通列表而不是numpy数组,所有这些也都使用效率较低(在时间和空间上)的默认JSON编码进行编码,而不是使用numpy数组的有效二进制编码。

就是说,这并没有在这里引起所有问题,并且可能不是一个解决方案。但我想确保指出这一点。

数据着色器

对于这许多点,您可以考虑将DataShader与Bokeh结合使用。 Holoviews库还自动高度集成了Bokeh和Datashader。通过在Python端上预渲染图像,Datashader实际上是一种带宽压缩工具(除其他外)。

PNG导出

散景倾向于在提供各种交互性之间进行权衡。但是,如果您实际上不需要这种交互性,那么您将付出一些额外的费用。如果是这种情况,您可以考虑生成静态PNG,而不是:

from bokeh.io.export import get_screenshot_as_png
p = get_screenshot_as_png(plot)

散景:在jupyter实验室重复绘制会增加(浏览器)的内存使用量 - python

您需要安装Exporting Plots中列出的其他可选依赖项,并且如果要进行许多绘图,则可能需要考虑为每个调用显式保存和重用Webdriver。

Python sqlite3数据库已锁定 - python

我在Windows上使用Python 3和sqlite3。我正在开发一个使用数据库存储联系人的小型应用程序。我注意到,如果应用程序被强制关闭(通过错误或通过任务管理器结束),则会收到sqlite3错误(sqlite3.OperationalError:数据库已锁定)。我想这是因为在应用程序关闭之前,我没有正确关闭数据库连接。我已经试过了: connectio…

如何在Jupyter笔记本中导入CPLEX? - python

我是Python和Jupyter笔记本的新手。我正在使用Windows 10。我已经安装了Anaconda3,并尝试在Jupyter笔记本环境中导入cplex。但是我只有以下错误:  ModuleNotFoundError:没有名为“ cplex”的模块我确实找到了一些解决方案,但是都没有解决问题。我认为我必须设置路径或安装一些文件才能在Jupyetr笔记本…

Python:传递记录器是个好主意吗? - python

我的Web服务器的API日志如下:started started succeeded failed 那是同时收到的两个请求。很难说哪一个成功或失败。为了彼此分离请求,我为每个请求创建了一个随机数,并将其用作记录器的名称logger = logging.getLogger(random_number) 日志变成[111] started [222] start…

Python pytz时区函数返回的时区为9分钟 - python

由于某些原因,我无法从以下代码中找出原因:>>> from pytz import timezone >>> timezone('America/Chicago') 我得到:<DstTzInfo 'America/Chicago' LMT-1 day, 18:09:00 STD…

用大写字母拆分字符串,但忽略AAA Python Regex - python

我的正则表达式:vendor = "MyNameIsJoe. I'mWorkerInAAAinc." ven = re.split(r'(?<=[a-z])[A-Z]|[A-Z](?=[a-z])', vendor) 以大写字母分割字符串,例如:'我的名字是乔。 I'mWorkerInAAAinc”变成…