# Performance drop after usage (wslink + vtk)

**URL:** https://discourse.vtk.org/t/performance-drop-after-usage-wslink-vtk/15038
**Category:** Web
**Created:** [December 17, 2024, 6:16pm UTC](https://discourse.vtk.org/t/performance-drop-after-usage-wslink-vtk/15038 "2024-12-17T18:16:01Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![joaomlap](https://discourse.vtk.org/user_avatar/discourse.vtk.org/joaomlap/32/3201_2.png) [@joaomlap](https://discourse.vtk.org/u/joaomlap)
#### Post date: [December 17, 2024, 6:16pm UTC](https://discourse.vtk.org/t/performance-drop-after-usage-wslink-vtk/15038/1 "2024-12-17T18:16:01Z")

</div>

Hi again 🙂

I am building a web application with wslink + vtk (python wrapper).

I am rendering a fairly big model on the server, everything starts smooth and the model renders correctly with an acceptable number of FPS.

After just utilising rotating it around the performance starts to drop and everything on the server gets very slow. Every message any new request is now much slower and it never recovers.

Is there a cache being created that could be cleaned? I am not sure what I can pursue here.

I already am setting interactive ratios and interactive quality but the key thing is the more events I send (using mouse interactions) over time the slower it gets, and it never recovers.

---

<div class="post-metadata">

### Author: ![joaomlap](https://discourse.vtk.org/user_avatar/discourse.vtk.org/joaomlap/32/3201_2.png) [@joaomlap](https://discourse.vtk.org/u/joaomlap)
#### Post date: [December 19, 2024, 12:04pm UTC](https://discourse.vtk.org/t/performance-drop-after-usage-wslink-vtk/15038/2 "2024-12-19T12:04:35Z")

</div>

Wanted to add that this occurs (either only or at least much faster) when more than one view (render\_window) is created in the server.

I am actively unregistering views not on display.

The images from other views are not being sent but they are affecting.

Here’s a minimalist server code:

```python
class MyProtocols(vtkWebProtocol):
    started = False

    def render(self, data: vtk.vtkMultiBlockDataSet):
        """
        Render the data.
        """
        self.render_window = vtk.vtkRenderWindow()
        self.renderer = vtk.vtkRenderer()
        self.render_window.AddRenderer(self.renderer)
        self.interactor = vtk.vtkRenderWindowInteractor()
        self.interactor.SetInteractorStyle(vtk.vtkInteractorStyleTrackballCamera())
        self.interactor.SetRenderWindow(self.render_window)
        self.render_window.SetOffScreenRendering(1)

        self.actor = vtk.vtkActor()
        self.mapper = vtk.vtkCompositePolyDataMapper()
        self.actor.SetMapper(self.mapper)
        self.mapper.SetInputDataObject(data)
        self.renderer.AddActor(self.actor)

        self.render_window.Render()

        return self.render_window

    @register("start")
    def start(self):
        if self.started:
            return
        self.started = True

        data = load_data()
        view_ids = []

        for _ in range(0, 4):
            rw = self.render(data)
            view_id = self.getGlobalId(rw)
            view_ids.append(view_id)

        return view_ids

```

React (remote render code):

```auto
import React, { useEffect, useLayoutEffect, useRef, useState } from "react";
import vtkRemoteView from "@kitware/vtk.js/Rendering/Misc/RemoteView";
import vtkViewStream from "@kitware/vtk.js/IO/Core/ImageStream/ViewStream";

interface RemoteViewerProps {
  client: any;
  viewStream: vtkViewStream;
  registerViewStream: (viewStream: vtkViewStream) => void;
  unregisterViewStream: (viewStream: vtkViewStream) => void;
}

export const RemoteViewer = React.memo(
  ({
    viewStream,
    client,
    registerViewStream,
    unregisterViewStream,
  }: RemoteViewerProps) => {
    const ref = useRef<HTMLDivElement>(null);
    const [remoteView, setRemoteView] = useState<vtkRemoteView | null>(null);
    let result: React.ReactNode;

    useEffect(() => {
      if (viewStream) {
        // Unregister first to prevent duplicates
        unregisterViewStream(viewStream);
        // The register method does not check for existing viewStreams
        registerViewStream(viewStream);
      }

      const setup = async () => {
        if (
          typeof window !== undefined &&
          client &&
          ref.current &&
          !remoteView
        ) {
          const session = client.getConnection().getSession();

          const vtkRemoteView = await import(
            "@kitware/vtk.js/Rendering/Misc/RemoteView"
          );
          const newView = vtkRemoteView.newInstance({
            rpcWheelEvent: "viewport.mouse.zoom.wheel",
            viewStream,
          });

          newView.setSession(session);
          newView.setInteractiveRatio(0.9); // the scaled image compared to the clients view resolution
          newView.setInteractiveQuality(70); // jpeg quality

          newView.setContainer(ref.current);
          newView.resize();
          window.addEventListener("resize", newView.resize);
          ref.current.addEventListener("resize", newView.resize);

          setRemoteView(newView);
        } else if (!client && remoteView) {
          setRemoteView(null);
        }
      };

      setup();

      return () => {
        if (viewStream) {
          unregisterViewStream(viewStream);
        }
      };
    }, [ref, client, remoteView, viewStream]);

    if (client) {
      result = (
        <div
          style={{
            width: "100%",
            height: "100%",
            overflow: "hidden",
            position: "relative",
            background: "none",
          }}
          ref={ref}
        />
      );
    }

    return result;
  }
);

RemoteViewer.displayName = "RemoteViewer";

```

---

<div class="post-metadata">

### Author: ![joaomlap](https://discourse.vtk.org/user_avatar/discourse.vtk.org/joaomlap/32/3201_2.png) [@joaomlap](https://discourse.vtk.org/u/joaomlap)
#### Post date: [December 19, 2024, 11:47pm UTC](https://discourse.vtk.org/t/performance-drop-after-usage-wslink-vtk/15038/3 "2024-12-19T23:47:38Z")

</div>

I think it might be related to `vtkWebMouseHandler` and `vtkWebPublishImageDelivery` in VTK protocols.

I am not sure if this is the only problem or the one causing, but it seems that the `action` property on the event is always `down` which in turn creates a StartInteractionEvent multiple times before calling finally EndInteractionEvent.

I’ve noticed that `viewsInAnimation` does not get cleared as intended, or at least to my level of understanding. It seems that we push the same `viewId` over and over to the `viewsInAnimation` array until it gets cleared only 1 times on the end event.

This after some time from my understanding is causing degradation in the streaming protocol.

I am not 100% sure on how the code works so it could be on purpose but it seems like this is causing a leak which in turn forces more renderings than necessary.

---

<div class="post-metadata">

### Author: ![joaomlap](https://discourse.vtk.org/user_avatar/discourse.vtk.org/joaomlap/32/3201_2.png) [@joaomlap](https://discourse.vtk.org/u/joaomlap)
#### Post date: [December 20, 2024, 12:24am UTC](https://discourse.vtk.org/t/performance-drop-after-usage-wslink-vtk/15038/4 "2024-12-20T00:24:57Z")

</div>

Again without knowing 100% of the code I think the `vtkRemoteView` with its interactorStyle `vtkInteractorStyleRemoteMouse` sends Start and End events correctly on it’s own, i.e. `StartInteractionEvent` and `EndInteractionEvent`. So it could be that without this bit:

```python
if event["action"] == "down":
    self.getApplication().InvokeEvent("StartInteractionEvent")

if event["action"] == "up":
    self.getApplication().InvokeEvent("EndInteractionEvent")

```

in

```python
class vtkWebMouseHandler(vtkWebProtocol):
    @exportRpc("viewport.mouse.interaction")
    def mouseInteraction(self, event):

```

is actually irrelevant and in this case causing the leak, but I’m not sure if it’s being used elsewhere, what I know here is that `action` is always `down` until it is `up` thanks to the way the interactor is created:

```javascript
function createRemoteEvent(callData) {
    // Fields:
    // - action: [down, up]
    // - x, y (Normalized)
    // Flags:
    // - buttonLeft, buttonMiddle, buttonRight
    // - shiftKey, ctrlKey, altKey, metaKey
    const {
      buttonLeft,
      buttonMiddle,
      buttonRight
    } = model;
    const shiftKey = callData.shiftKey ? 1 : 0;
    const ctrlKey = callData.controlKey ? 1 : 0;
    const altKey = callData.altKey ? 1 : 0;
    const metaKey = callData.metaKey ? 1 : 0; // Might be platform specific
    const action = buttonLeft || buttonMiddle || buttonRight ? 'down' : 'up';

    // Fixme x / y
    const [width, height] = model._interactor.getView().getSizeByReference();
    let {
      x,
      y
    } = callData.position;
    x /= width;
    y /= height;
    return {
      action,
      x,
      y,
      buttonLeft,
      buttonMiddle,
      buttonRight,
      shiftKey,
      altKey,
      ctrlKey,
      metaKey,
      ...model.remoteEventAddOn
    };
  }

```

As we can see there action is always `down` or `up` causing the beforementioned problem.

---

<div class="post-metadata">

### Author: ![Sebastien\_Jourdain](https://discourse.vtk.org/user_avatar/discourse.vtk.org/sebastien_jourdain/32/100_2.png) [@Sebastien\_Jourdain](https://discourse.vtk.org/u/Sebastien_Jourdain)
#### Post date: [December 20, 2024, 3:45am UTC](https://discourse.vtk.org/t/performance-drop-after-usage-wslink-vtk/15038/5 "2024-12-20T03:45:16Z")

</div>

Can you reproduce that issue in a small trame example? That might be easier to track down and fix.

---

<div class="post-metadata">

### Author: ![joaomlap](https://discourse.vtk.org/user_avatar/discourse.vtk.org/joaomlap/32/3201_2.png) [@joaomlap](https://discourse.vtk.org/u/joaomlap)
#### Post date: [January 14, 2025, 10:53am UTC](https://discourse.vtk.org/t/performance-drop-after-usage-wslink-vtk/15038/6 "2025-01-14T10:53:37Z")

</div>

Hi Sebastien sorry for the long delay, I have been away.

So from my experiment this will happen on **any** VTK/WsLink project. If you create any sandbox project and put a debugger somewhere on the tracking views you will see that the list only gets bigger and bigger because all the events while mouse is down are characterised as DOWN and appending the view ID to tracking views.

---

<div class="post-metadata">

### Author: ![Sebastien\_Jourdain](https://discourse.vtk.org/user_avatar/discourse.vtk.org/sebastien_jourdain/32/100_2.png) [@Sebastien\_Jourdain](https://discourse.vtk.org/u/Sebastien_Jourdain)
#### Post date: [January 15, 2025, 8:29pm UTC](https://discourse.vtk.org/t/performance-drop-after-usage-wslink-vtk/15038/7 "2025-01-15T20:29:31Z")

</div>

Can you make a small python example with trame and VTK that reproduce that behavior? Like I said, it will be easier for me to look at it and fix the issue.
