Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Fix HTJ2K decoder leak #1388

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

abustany
Copy link
Contributor

Context

Commit 85fd193 changed decodeHTJ2K.js to allocate a new HTJ2KDecoder with each call to decodeAsync. The old decoders somehow stay alive, and are not cleaned from the WASM memory. Each new HTJ2KDecoder allocates in turns buffers for the encoded and decoded pixel data while decoding.

Changes & Results

The change to allocate a new decoder per frame argued that reusing the old decoder is "much slower", but I could not reproduce any slowdowns either in the browser or on Node. This commit therefore reverts the change, so that each call to decodeAsync reuses the same decoder instance.

Testing

Checklist

PR

  • My Pull Request title is descriptive, accurate and follows the
    semantic-release format and guidelines.

Code

Public Documentation Updates

  • [] The documentation page has been updated as necessary for any public API
    additions or removals.

Tested Environment

  • "OS: Linux
  • "Node version: 20.11
  • "Browser: Chrome 126, Firefox 128

Commit 85fd193 changed decodeHTJ2K.js
to allocate a new HTJ2KDecoder with each call to decodeAsync. The old
decoders somehow stay alive, and are not cleaned from the WASM memory.
Each new HTJ2KDecoder allocates in turns buffers for the encoded and
decoded pixel data while decoding.

The change to allocate a new decoder per frame argued that reusing the
old decoder is "much slower", but I could not reproduce any slowdowns
either in the browser or on Node. This commit therefore reverts the
change, so that each call to decodeAsync reuses the same decoder
instance.
Copy link

netlify bot commented Jul 11, 2024

Deploy Preview for cornerstone-3d-docs ready!

Name Link
🔨 Latest commit e72f82a
🔍 Latest deploy log https://app.netlify.com/sites/cornerstone-3d-docs/deploys/668fb02986ad0c0008023b5a
😎 Deploy Preview https://deploy-preview-1388--cornerstone-3d-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@sedghi sedghi requested a review from wayfarer3130 July 12, 2024 19:34
@@ -57,8 +57,7 @@ export function initialize(decodeConfig?: LoaderDecodeOptions): Promise<void> {
// https://github.com/chafey/openjpegjs/blob/master/test/browser/index.html
async function decodeAsync(compressedImageFrame: ByteArray, imageInfo) {
await initialize();
// const decoder = local.decoder; // This is much slower for some reason
const decoder = new local.codec.HTJ2KDecoder();
const decoder = local.decoder;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This was the original implementation, but it causes a bug where some images can't be decoded and the decoding gets slower and slower over time.
The problem is that some of the state in the decoder isn't being cleared correctly. I would try updating the openjph library to latest, make sure the malloc library used is the same one we use for openjpeg, and rebuild that part of the system. Then you can test to see if it works using the CS3D progressive loading tests. Test the decompression time for the second decompression, and then for the last decompression time on the HTJ2K volume, as well as running the HTJ2K stack tests, with multiple runs through the stack. The decompression time should stay roughly constant.

@@ -57,8 +57,7 @@ export function initialize(decodeConfig?: LoaderDecodeOptions): Promise<void> {
// https://github.com/chafey/openjpegjs/blob/master/test/browser/index.html
async function decodeAsync(compressedImageFrame: ByteArray, imageInfo) {
await initialize();
// const decoder = local.decoder; // This is much slower for some reason
const decoder = new local.codec.HTJ2KDecoder();
const decoder = local.decoder;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should be
const { decoder } = local;

@wayfarer3130
Copy link
Collaborator

If you update this PR to include an openjph version change for the release after cornerstonejs/codecs#46
then I will approve the PR and merge it.

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.

2 participants