From a full data-transport audit at b0f8780.
Today: lod.BufferWriter.add_f32/add_u8 do ascontiguousarray(...).tobytes() (python/xy/lod.py:744-757) — tobytes() is always a copy. Same pattern at _encode_log_u8 (python/xy/interaction.py:413-418) and selection-mask replies (python/xy/channel.py:137, python/xy/_figure.py:1560). For a 200k-point drill-in (x, y, color, size, density_val ≈ 4 MB) that is ~4 MB of pure copy per zoom step, on the interaction-latency path.
Proposed fix: retain arrays and expose memoryviews (arr.data.cast(\"B\")) exactly like _PayloadWriter.buffers() does for first paint (python/xy/_payload.py:154-160) — the anywidget comm and encode_frame_parts both accept memoryviews; the socket.io transport already converts to bytes itself in _buffer_bytes.
From a full data-transport audit at b0f8780.
Today:
lod.BufferWriter.add_f32/add_u8doascontiguousarray(...).tobytes()(python/xy/lod.py:744-757) —tobytes()is always a copy. Same pattern at_encode_log_u8(python/xy/interaction.py:413-418) and selection-mask replies (python/xy/channel.py:137,python/xy/_figure.py:1560). For a 200k-point drill-in (x, y, color, size, density_val ≈ 4 MB) that is ~4 MB of pure copy per zoom step, on the interaction-latency path.Proposed fix: retain arrays and expose memoryviews (
arr.data.cast(\"B\")) exactly like_PayloadWriter.buffers()does for first paint (python/xy/_payload.py:154-160) — the anywidget comm andencode_frame_partsboth accept memoryviews; the socket.io transport already converts tobytesitself in_buffer_bytes.