Skip to content

Optimize addImage for image streaming: fast path bypasses full pipeline#4524

Open
physwkim wants to merge 4 commits intosilx-kit:mainfrom
physwkim:optimize-addimage-fast-path
Open

Optimize addImage for image streaming: fast path bypasses full pipeline#4524
physwkim wants to merge 4 commits intosilx-kit:mainfrom
physwkim:optimize-addimage-fast-path

Conversation

@physwkim
Copy link
Copy Markdown
Contributor

Summary

While testing large image handling for another PR
#4520

I noticed a performance bottleneck when streaming large images (~4096×4096) using addImage(). Each frame update goes through the full pipeline:


dirty → remove → add backend renderer

For streaming scenarios where the image shape does not change, this introduces unnecessary overhead (renderer recreation, colormap recomputation, and extra data copies).

This PR introduces a fast path allowing the backend renderer to update image data directly when possible.


Changes

Renderer fast path

If the following conditions are met:

  • renderer exists
  • renderer supports updateData
  • image shape is unchanged
  • no alternative or alpha image

then ImageDataBase.setData() directly calls:


renderer.updateData(data, clim)

This bypasses the remove/add renderer cycle.


Avoid redundant setActiveImage() calls

PlotWidget.addImage() now avoids calling setActiveImage() if the image is already active, preventing unnecessary signal disconnect/reconnect during streaming.


Fix unnecessary double copy

ImageData.setData() previously triggered an additional copy through:

super().setData(data)

This PR changes it to:

- super().setData(data)
+ super().setData(data, copy=False)

File:

src/silx/gui/plot/items/image.py

This avoids an extra ~64MB memory copy per frame for a 4096×4096 float32 image.


Performance (4096×4096 float32)

Mode FPS
Before ~49
After (copy=True) ~65
After (copy=False) ~92

Notes

This optimization was discovered while investigating performance issues during large image testing in PR #4520.

The fast path is conservative and activates only when safe, without introducing new public APIs.

When updating an existing image with same-shape data and the backend
renderer supports direct updates (updateData), bypass the full item
dirty/remove/add cycle and update the renderer directly.

Fast path conditions:
- Backend renderer exists and has updateData method
- Data shape is unchanged from previous frame
- No alternative/alpha images provided (ImageData)

Changes:
- ImageData.setData: early fast path before data copy
- ImageDataBase.setData: direct renderer update when shape unchanged
- PlotWidget.addImage: skip redundant setActiveImage on same image
- Fix double copy in ImageData.setData (copy=False to super)
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.

1 participant