Different ways to terminate a WebAssembly process from inside a web worker

In my web application, I have a wasm process (compiled from c++) that processes data. The code for this process is as follows:

std::vector<JSONObject> data
for (size_t i = 0; i < data.size(); i++)
{
    process_data(data[i]);

    if (i % 1000 == 0) {
        bool is_cancelled = check_if_cancelled();
        if (is_cancelled) {
            break;
        }
    }

}

This code essentially simulates running/processing a query like a SQL query interface:

https://i.sstatic.net/WKPws.png

Queries may take minutes to complete and the user has the option to cancel their query at any time. The cancellation process happens in the normal javascript/web application, not within the service Worker where the wasm is running.

My concern is how to notify the wasm process when the user cancels their query so it can exit properly. Terminating the worker with worker.terminate() is not an option because we need to keep all loaded data for that worker. It needs to remain active so another query can be executed.

How can we effectively communicate between the javascript and worker/wasm/c++ application to know when to exit gracefully?

Additionally, let's assume a standard query takes 60s to execute and processes 500MB of data using cpp/wasm in-browser.


Update: After some research and feedback, here are some potential solutions along with their feasibility:

  1. Using two workers - one to store data and another to process it. However, transferring large amounts of data would be time-consuming and inefficient.

  2. Utilizing Emterpreter and emscripten_sleep_with_yield, but this significantly impacts performance.

  3. Running a second worker while displaying only the most recent data on UI, potentially causing memory errors.

  4. Sending API calls to a server to track query status, but it involves frequent network requests adding unnecessary overhead.

  5. Implementing an incremental-parsing approach by rewriting parsing functions, which could be labor-intensive.

  6. Storing status in IndexedDB, allocating memory in WASM, and processing data in C++, which seems promising but requires further exploration.

  7. [Any other suggestions?]

For the bounty, I'm seeking answers to these questions:

  1. Are the six proposed solutions valid?
  2. Are there better alternatives worth considering?
  3. Can someone demonstrate a basic example of #6, assuming it works universally across browsers?

Answer №1

To optimize performance in Chrome, consider utilizing shared memory for storing data and setting a flag to halt processes when necessary. However, this solution is complex and only supported on the Chrome browser. It also relies on the structure of your queries and whether there are checkpoints to check the halt flag.

Alternatively, calling the C++ function multiple times, once for each query, and checking for a halt signal after each call may be a better approach. Breaking down the query into stages through multiple function calls could also be beneficial depending on your specific scenario.

Unfortunately, there is no direct way to send a signal to a WebAssembly execution like Linux kill. As a result, you'll need to wait for the operation to complete before being able to cancel effectively.

If user experience is a priority, consider using two workers to handle tasks. While this will increase memory usage, it allows for more immediate cancellations by switching to the second worker to process subsequent queries while the first handles cancellation requests.

Answer №2

Thread Sharing

When a worker and a C++ function share the same thread, the worker will be blocked until the C++ loop is complete, unable to handle any incoming messages. To reduce blocking time, it may be more efficient to initialize one iteration at a time from the main application.

The process would resemble:

main.js  ->  worker.js  ->  C++ function  ->  worker.js  ->  main.js

Breaking Down the Loop

In this scenario, a variable in C++ is set to 0, incrementing with each loop iteration and stored in memory. The C++ function executes one loop iteration, increments the variable for tracking, and then halts.

int x;
x = 0;

std::vector<JSONObject> data
for (size_t i = x; i < data.size(); i++)
{
    process_data(data[i]);

    x++
    break;
}

Subsequently, a message can be sent to the web worker, alerting main.js that the thread is unblocked.

Cancelling Operations

Main.js receives confirmation that the web worker’s thread is free and can determine whether to instruct the web worker to repeat the C++ function, maintaining the loop counter in memory.

let continueOperation = true

worker.expensiveThreadBlockingFunction()

worker.onmessage = function(e) {
    if (continueOperation) {
        worker.expensiveThreadBlockingFunction()
    } {
        return false
    }
}

Resuming Operations

If all is proceeding smoothly and operation cancellation has not occurred, the loop should progress uninterrupted. Ensure distinct messaging indicating loop completion or continuation to prevent undue worker thread blockage.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to determine if a value exists within an array of objects?

Is it possible to determine if a specific value is present in an array of objects? I've tried a method, but it always returns false. What would be the most effective way to solve this issue? My approach: var dog_database = [ {"dog_name": "Joey" ...

Top techniques for creating a popup window with React

I'm working on my React application and I'm looking to implement a popup window that displays a table with some data. However, I want this popup to appear in a separate browser window rather than as a modal attached to the application's DOM. ...

Guide to displaying or hiding elements based on the number of selected checkboxes

When only one checkbox is checked, all buttons in the head-btn class should be displayed. By default, only the add folder and upload buttons are shown. If a user selects two checkboxes, the share button should be hidden. If they uncheck one of the checkbo ...

Can a callback in an ES6 class constructor ensure that the promise is either resolved or rejected?

I'm currently puzzled by the concept of using a callback function that always returns an empty object and then passing a parameter to this callback. Visit this link for more information My assumption is that this approach ensures that the Promise wi ...

Error in SO Embed Snippet Fiddle due to Bootstrap 4 JS Issue

Just wondering, any idea why the bootstrap 4 js is throwing this error: https://i.sstatic.net/J4Iq4.png when trying to embed the snippet? (No errors in the external Fiddle) Added tether.js but no luck (kept it commented). Switched to jQuery 2.2.1 on th ...

Issue with jQuery AJAX call: When submitting an HTML form, control is not being returned to the calling

I am facing an issue with my HTML form where it is loaded correctly into the DOM through a jQuery ajax call. The problem arises when I submit the form data to a PHP module using another jQuery ajax call. Even though the network traffic shows that the form ...

Error: npm encountered a socket timeout issue

Setting up a fresh React application in /home/abhijith/Desktop/React/firstReact/myapp. Installing necessary packages. This process may require a few minutes. Installing react, react-dom, and react-scripts along with cra-template... npm ERR! code ERR_SOCK ...

Validation of Ajax using the JQuery Form Validation Plugin

I have integrated the jQuery form validation plugin in my project, which can be found at When the form is invalid, my server responds with data in a name pair combination format like this: data: email:"Is invalid" name" "Is invalid" Can I ...

Efficiently transform unprocessed data into a hexadecimal string using c++

I am currently working on reading data from a file and displaying the raw data as 2 digit hex strings. My tool of choice is the Qt framework, specifically utilizing the QTextEdit feature. Despite trying various methods, I have come close to achieving my ...

Utilizing v-model for dynamic binding within a v-for iteration

I'm currently working on binding v-model dynamically to an object property within an array of objects. I am unsure about how to accomplish this task. The objective is to choose a user using the Select HTML tag and then display the list of that user&ap ...

RShiny encountering issues while trying to load external HTML file along with CSS file

I've been working on a Shiny app, where I put together the UI code using HTML, CSS, and JavaScript within the www sub-folder, while keeping the app.R file in the main folder. The code in my app is structured as follows: runApp( shinyApp( ui = sh ...

haphazardly showcase circular shapes within a confined space

Is there a way to display circles randomly inside a box without them extending beyond the box or touching its corners? Can the circles be plotted using relative values (percent) within the div? For example, can a circle be placed 10% from the left side and ...

"You are unable to modify headers once they have been sent to the client, and an unhandled promise has been

Every time I run this code block, I encounter the following error message - UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client UnhandledPromiseRejectionWarning: Unhandled promise rejectio ...

What steps can be taken to provide accurate information in the absence of ImageData?

Utilizing a JS library to convert a raster image into a vector, I encountered an issue where the library returned a fill of solid color instead of the desired outcome. I suspect that the problem lies within the ArrayBuffer. The process of loading an imag ...

Unable to modify the selector to "Remove preview files" on click in PHP and JavaScript

During the process of uploading multiple files (using <input type="file" multiple/>) with preview image file and successfully removing the image preview and file data, I encountered a problem. The issue arises when attempting to change the selector ...

Incorporating a navigation bar into my Jade template

I am working with nodejs, express, and bootstrap for my project. While this may seem like a basic question, I have been unable to find the specific solution I need. My issue lies in the fact that I have a layout.jade file and an index.jade file, with the ...

Arranging a collection of nested vectors

My question involves a vector of vectors containing integers structured as follows: std::vector<std::vector<int>> vec_vec{{3,5,1,6},{2,4},...}; The desired outcomes are: Case1: {{1, 2, 3, 4}, {5, 6}} Case2: {1,2,3,4,5,6} Case3: {{1, ...

Insert analytics code post-button click permission granted in Next.js/React

Need help with activating analytics scripts upon a button click? I have analytics scripts that I want to add to my next.js website only if the user opts in. When a button in my CookieBanner component is clicked, a cookie is set to track if the user has o ...

Using GLFW within a class can result in an argument of type `<C++ class method>` being incompatible with a parameter of type `GLFWwindowsizefun`

Currently in the process of refactoring my code into a class called VkAPP. While doing so, I encountered this error: The argument type "void (VkAPP::)(GLFWwindow window, int width, int height)" is incompatible with the parameter type "GLFWwindowsizefun" ...

A guide on incorporating `executeScript` in Rselenium for emulating the activation of hotkeys

While RSelenium is a useful package for interfacing with the web using R, it falls short when it comes to utilizing hotkeys to run external functions or activate extensions programmatically. One idea I'm exploring is using a javascript command to sim ...