2

When using transferable objects in my shared workers I receive null for event.data in the main thread. After some searching I found this post where is explained that the ArrayBuffer is always lost when it is passed through a MessagePort of a MessageChannel.

Shared worker communication is also done using ports and message channels. Does this mean that there is no way to use transferable objects in a SharedWorker instance? Or is there some workaround?

I need to transfer a huge string from SharedWorkerGlobalScope back to the main thread. The idea is to convert it to an ArrayBuffer as shown in this example and then transfer the buffer. This is supposedly much faster then sending the string...

Sending the data:

var arrayBuffer = convertStringToArrayBuffer( string );

var data = {
    message: "here is an array buffer",
    arrayBuffer: arrayBuffer 
};

port.postMessage(data, [data.arrayBuffer]);

receiving the data:

worker.port.onmessage = function( event ) {

    // data is null
    var data = event.data;

}
Community
  • 1
  • 1
Wilt
  • 41,477
  • 12
  • 152
  • 203

1 Answers1

1

Just use postMessage without transferables. Strings are not transferable anyway (so it is always copied).

The goal of having transferables is to have a minimal cost when passing objects from the sender to the receiver. Such messages can cross process boundaries, and doing inter-process communication is expensive. This is the reason why transferables are not supported yet with MessagePort. Incidentally, difficulty in cross-process communication is also the reason why Safari dropped support for SharedWorkers.

Rob W
  • 341,306
  • 83
  • 791
  • 678
  • Thanks for looking at my question. I know a string is not a transferable, but I can easily convert it to an `ArrayBuffer` as shown in the example [here](https://developers.google.com/web/updates/2011/12/Transferable-Objects-Lightning-Fast?hl=en). Then I can sent the `ArrayBuffer`. This is for huge strings (maybe even 100Mb) supposedly much faster then sending the message without transferable. – Wilt Dec 09 '15 at 14:12
  • @Wilt Even if transferables work as intended, then your method doesn't give any performance savings (in theory). Instead of allocating a new buffer in the destination, you're just allocating the buffer in the source thread and then passing the buffer to the destination. But transferables are not supported in Chrome (for the reasons given in my answer), so it's not likely that you can find a work-around that has the desired performance characteristics. Therefore you can just go for simplicity, and not use transferables. – Rob W Dec 09 '15 at 14:16
  • Okay. Thanks for your answer. I will consider a solution without transferable... It seemed nice to be able to test this and see with my own eyes if I could gain some performance increase. – Wilt Dec 09 '15 at 14:19
  • @Wilt Do you really need shared workers though? Transferables work just fine in a normal Web worker, so unless there is a strong reason for using SharedWorkers, I'd just use a normal worker. Taking this even further: Do you really need workers at all? If e.g. the string is the result of a network request, then sending the request from the main thread is equally effective. – Rob W Dec 09 '15 at 14:22
  • We need workers. The string is a result of an intensive parsing process. Our UI used to be totally frozen during the parsing. We use SharedWorkers now so we can do parsing of a huge queue simultaneously with several workers. We got great performance increase when using WebWorkers and our UI is responsive during parsing. So all is working nicely... – Wilt Dec 09 '15 at 14:35
  • @Wilt In your description, I don't see a strong reason for using SharedWorkers over WebWorkers. Try using WebWorkers for better performance, and if you really need to share workers with other tabs (e.g. to synchronize data, or to terminate a worker in one tab so that you can launch a worker in another tab (browsers limit the number of workers per origin)), use a single SharedWorker to manage the communication. – Rob W Dec 09 '15 at 14:39