AdjointLayout with image, vline and hline kills performance and makes bokeh spam

Hi,

I ran into another panel 0.14 => 1.0 problem.
Otherwise I must say it’s going much better with 1.2.1 than 1.1.1. Awesome work everyone involved!

So I have a component for measuring vignetting of a camera. I attach a repex which spams the log completely with messages like:

2023-08-10 13:43:37,990 Dropping a patch because it contains a previously known reference (id='p118488'). Most of the time this is harmless and usually a result of updating a model on one side of a communications channel while it was being removed on the other end.

I might very well be doing something stupid here, but I did not get this performance hit in 0.14.

Python 3.10.10
Panel: 1.2.1
Bokeh: 3.2.1
Param: 1.13.0

Code to reproduce:

import panel as pn
import numpy as np
import numpy as np
import holoviews as hv
from holoviews import opts
from holoviews.core import AdjointLayout
import param
import random

hv.extension("bokeh")

xmax, ymax = 3208, 2200

# Make hv.Images objects
scale_factor = 5.25
bounds = (0, 0, xmax, ymax)  # Coordinate system: (left, bottom, right, top)
options = [
    opts.Image(
        cmap="gray",
        aspect="equal",
        frame_width=int(xmax / scale_factor),
        frame_height=int(ymax / scale_factor),
        xaxis=None,
        yaxis=None,
    )
]
xopts = [opts.Curve(frame_height=int(ymax / scale_factor))]
yopts = [opts.Curve(frame_width=int(xmax / scale_factor))]

# Define interactivity
x = pn.widgets.IntSlider(start=0, end=xmax, value=int(xmax / 2))
y = pn.widgets.IntSlider(start=0, end=ymax, value=int(ymax / 2))


class Dummy(param.Parameterized):
    latest = param.Parameter(default=(np.ones(shape=(50, 50), dtype=np.uint16) * 2000))

global dummy
dummy = Dummy()


@pn.depends(image=dummy.param.latest, x=x, y=y, watch=False)
def img0(image, x, y):
    image = hv.Image(image, bounds=bounds).opts(*options)
    layout = AdjointLayout(
        data={"main": image.opts(options) * hv.HLine(y=y) * hv.VLine(x=x), "top": image.sample(y=y, bounds=bounds).opts(yopts), "right": image.sample(x=x, bounds=bounds).opts(xopts)}
    )
    return layout

# Create panel layout
vignetting = pn.Column(
    pn.Row(x, y),
    img0,
    width=800, height=600,
)

vignetting.servable()

def update():
    global dummy
    dummy.latest = (np.ones(shape=(50, 50), dtype=np.uint16) * random.randint(1, 4000))

cb = pn.state.add_periodic_callback(update, 200)

Best regards,
Fredrik