
I’m not sure if I’m overlooking something but it seems like that ndarrays are encoded as a buffer just to be later encoded as base64. Is that expected?
In the PayloadEncoder ( bokeh/src/bokeh/core/json_encoder.py at dd25b9157afe5e04de35d0f3bfa80715f4a2422b · bokeh/bokeh · GitHub ) the document object will contain the ndarray as a Buffer object, however as self._buffer is just an empty list (not sure why?) obj.to_base64() will get called on the encoded ndarrays.
Maybe I miss something but to me it seem like that buffers are not set correctly in the Serializer.
def default(self, obj: Any) -> Any:
if isinstance(obj, Buffer):
if obj.id in self._buffers: # TODO: and len(obj.data) > self._threshold:
return obj.ref
else:
return obj.to_base64()
else:
return super().default(obj)
Full code example (data size can be adjusted as needed).
import numpy as np
from bokeh.io import curdoc, show
from bokeh.layouts import row
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
n_splits = 100
n_split_samples = 20_000
cds_standard = ColumnDataSource(data={"x":[], "y":[]})
cds_multi = ColumnDataSource(data={"x":[], "y":[]})
cds_scatter = ColumnDataSource(data={"x":[], "x2": [], "y":[]})
for i in range(n_splits):
x_data = np.arange(n_split_samples)
y_data = np.sin(x_data/100) + x_data/500*np.random.randn()
cds_standard.stream({"x": x_data, "y": y_data})
cds_multi.stream({"x": [np.append(x_data, x_data[0])], "y": [np.append(y_data, y_data[0])]})
cds_scatter.stream({"x": x_data, "x2": -x_data, "y": y_data})
p1 = figure(title="Single line", output_backend="webgl")
p2 = figure(title="Multi line", output_backend="webgl")
p3 = figure(title="Scatter", output_backend="webgl")
p1.line(x="x", y="y", source=cds_standard)
p2.multi_line(xs="x", ys="y", source=cds_multi)
p3.scatter(x="x", y="y", source=cds_scatter, size=1)
curdoc().add_root(row(p1, p2, p3))


