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

feat(webworker): Simplify the API for running a compute task off the main thread in a worker #891

Merged
merged 38 commits into from
Nov 21, 2023

Conversation

sedghi
Copy link
Member

@sedghi sedghi commented Nov 15, 2023

Context

This PR reworks the web worker API and proposes a new set of methods to work with workers to make developers life so much easier to be able to run a function of the main thread

Changes & Results

adds webWorkerManager to the Core

Note: Currently, we will not transfer the decoders from the old web worker manager to this new one until the next version of cornerstone3D. The only thing you need to be careful is how many compute workers you create (on top of the decode workers which you can configure in the dicom image loader) so that your system can handle it.

Testing

Follow the steps here

https://deploy-preview-891--cornerstone-3d-docs.netlify.app/docs/concepts/cornerstone-core/webWorker

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:
  • [] "Node version:
  • [] "Browser:

Copy link

netlify bot commented Nov 15, 2023

Deploy Preview for cornerstone-3d-docs ready!

Name Link
🔨 Latest commit 5f31d08
🔍 Latest deploy log https://app.netlify.com/sites/cornerstone-3d-docs/deploys/655ce65884899d0008dcc527
😎 Deploy Preview https://deploy-preview-891--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.

webWorkerManager.js and improve console output in
example-runner-cli.js
@sedghi sedghi changed the title feat/workerpool compute feat(webworker): Simplify the API for running a compute task off the main thread in a worker Nov 15, 2023
@@ -99,7 +99,7 @@ async function run() {
toolGroup.addTool(WindowLevelTool.toolName);
toolGroup.addTool(PanTool.toolName);
toolGroup.addTool(ZoomTool.toolName);
toolGroup.addTool(StackScrollMouseWheelTool.toolName, { loop: true });
toolGroup.addTool(StackScrollMouseWheelTool.toolName, { loop: false });
Copy link
Collaborator

Choose a reason for hiding this comment

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

This seems unrelated - that is probably ok, but wasn't sure you intended to have this.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah the demo was feeling weird that is why i have it reverted

@@ -97,15 +97,15 @@ module.exports = function (config) {
},
// NOTE: For better debugging you can comment out the
// istanbul-instrumenter-loader below
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this be commented out - seems like this is a change to the coverage information we are seeing.

Copy link
Member Author

Choose a reason for hiding this comment

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

Karma hates the comlink package. coverageIstanbulReporter is responsible for coverage based on my understanding not this one

Prefetch = 'prefetch',
/** Lower priority, often used for background computations in the worker */
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think I would say instead that this request type does not consume bandwidth as it is local compute. Thus, it has a different queue to use. It is not whether the priority is lower or higher, it is different.

Copy link
Member Author

Choose a reason for hiding this comment

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

No, it is, in fact, lower in priority when queued. This should be comparing a decoding task versus a computation task.

Copy link
Collaborator

@wayfarer3130 wayfarer3130 left a comment

Choose a reason for hiding this comment

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

I think this looks good enough to start working with it. It might be worth adding a preliminary warning somewhere so that we acknowledge that the API might change a bit still to deal with any issues found, but generally I think it is reasonable.

Comment on lines +75 to +88
const workerInstances = workerProperties.instances.filter(
(instance) => instance !== null
);

let minLoadIndex = 0;
let minLoadValue = workerProperties.loadCounters[0] || 0;

for (let i = 1; i < workerInstances.length; i++) {
const currentLoadValue = workerProperties.loadCounters[i] || 0;
if (currentLoadValue < minLoadValue) {
minLoadIndex = i;
minLoadValue = currentLoadValue;
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

The worker could be found in O(1) if they were stored in a min-heap. But I don't think cornerstone has an implementation of a heap, right? At least the number of WebWorkers is very small and that should not impact the performance.

PS: requestPoolManager could also use a Priority Queue (max heap) instead of sorting the priorities whenever getNextRequest is called.

We can make that change in a near future if it's worth it. 😉

Copy link
Member Author

Choose a reason for hiding this comment

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

Makes a lot of sense, a good candidate for v2.x

}

// Update the load counter.
workerProperties.loadCounters[minLoadIndex] += 1;
Copy link
Collaborator

Choose a reason for hiding this comment

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

If there are 3 web workers for heavy computations and 15+ tasks (maxNumRequests.compute) each one would have 1 running + 4 in a Chrome/Comlink queue, right? As I commented in the previous PR my only concern is what happens with those tasks when "terminate" is called.

Copy link
Member Author

Choose a reason for hiding this comment

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

Add a comment about number of workers and load balancing

Comment on lines 119 to +123
this.maxNumRequests = {
interaction: 6,
thumbnail: 6,
prefetch: 5,
compute: 15,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe we should change maxNumRequests, requestType, etc. to a different name because before this change those three first options were related to image requests (download) but now compute was added and it is not related to that.

@sedghi sedghi merged commit 86876e5 into main Nov 21, 2023
9 checks passed
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.

None yet

3 participants