Skip to content

Sever pipe subscriptions when a cell widget is disposed - #1226

Merged
SimonHeybrock merged 2 commits into
mainfrom
1224-sever-pipe-subscribers-on-dispose
Aug 10, 2026
Merged

Sever pipe subscriptions when a cell widget is disposed#1226
SimonHeybrock merged 2 commits into
mainfrom
1224-sever-pipe-subscribers-on-dispose

Conversation

@SimonHeybrock

@SimonHeybrock SimonHeybrock commented Aug 10, 2026

Copy link
Copy Markdown
Member

Fixes #1224.

A cell rebuilt while its grid is visible left the discarded widget's rendered plot subscribed to the layers' hv.streams.Pipe: replacing the widget in the GridSpec slot does not run Panel's pane cleanup, so every SessionLayer.update_pipe drove the dead plot alongside the live one for the rest of the session — roughly doubling the dominant cost of the poll pass per rebuild, monotonically (see the issue for measurements).

CellWidget now keeps a handle on the pn.pane.HoloViews it builds, and dispose() runs Plot.cleanup() on the rendered plots and drops the pane's plot registry. dispose() already runs on rebuild, orphan removal, and document teardown, so all paths are covered.

One subtlety discovered while testing: Plot.cleanup()'s owner filter is defeated by holoviews' _WeakSubscriber wrapper (its __bool__ is False for any param-method subscriber, current upstream included), so cleanup severs every weakly-wrapped plot-refresh subscriber on the touched streams, not only its own. This is safe here because a layer's pipe is per session and per cell, and a rebuild disposes the displaced widget before the replacement renders — the docstring records the reasoning. Filed upstream as holoviz/holoviews#6988; the missing GridSpec cleanup itself is holoviz/panel#8710 (in-place objects mutation defeats the removed-child diff).

The sever uses the pane's private _plots registry, mirroring the pipe half of pn.pane.HoloViews._cleanup: Panel only runs that from a document root we no longer have, and exposes no public teardown.

Test plan

🤖 Generated with Claude Code

A cell rebuilt while its grid is visible left the discarded widget's
rendered plot subscribed to the layers' hv.streams.Pipe: replacing the
widget in the GridSpec slot does not run Panel's pane cleanup, so every
SessionLayer.update_pipe drove the dead plot alongside the live one for
the rest of the session, one extra rendering per rebuild (#1224).

CellWidget now keeps a handle on the pn.pane.HoloViews it builds and
dispose() runs Plot.cleanup() on the rendered plots and drops the pane's
plot registry. Plot.cleanup() severs every weakly-wrapped plot-refresh
subscriber on the touched streams, not only its own — holoviews treats
them all as reapable — which is safe because a layer's pipe is per
session and per cell, and a rebuild disposes the displaced widget before
the replacement renders.

Fixes #1224.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The missing GridSpec cleanup is holoviz/panel#8710 (in-place objects
mutation defeats the removed-child diff) and the over-broad Plot.cleanup
is holoviz/holoviews#6988; the TODO states when the sever block can be
deleted and where the regression tests move then.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@SimonHeybrock SimonHeybrock left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@SimonHeybrock
SimonHeybrock merged commit 86082a4 into main Aug 10, 2026
16 checks passed
@SimonHeybrock
SimonHeybrock deleted the 1224-sever-pipe-subscribers-on-dispose branch August 10, 2026 07:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cell rebuilt while its grid is visible leaves the old plot subscribed to the layer pipe

1 participant