0

I am writing a multi-threaded program. The main thread is constantly receiving network data, and the amount of data is relatively large, so sub-threads are used to process the data.

The received data is a 100-byte packet. Each time I receive a packet, I create a 100-byte SharedArrayBuffer and send it to the child thread via postMessage(). But the main thread receives the data very fast, so it is necessary to frequently call postMessage to notify the sub-thread, which leads to high CPU usage...affecting the response speed of the main thread

So I was thinking, if SharedArraybuffer can grow dynamically, the received data is constantly appended at the end of the SharedArrayBuffer, I only notify the child thread once, so that the child thread can also access the data.

I would like to ask how to dynamically increase the length of SharedArrayBuffer. I have tried to implement it in a chained way, storing a SharedArrayBuffer object in another SharedArrayBuffer object, but the browser does not allow this.

3 Answers3

0

I would like to ask how to dynamically increase the length of SharedArrayBuffer.

From MDN web docs (emphasis mine).

"The SharedArrayBuffer object is used to represent a generic, fixed-length raw binary data buffer, similar to the ArrayBuffer object, but in a way that they can be used to create views on shared memory."

Fixed-length means you can't resize it...so it's not surprising it doesn't have a resize() method.

(Note: One thing that does cross my mind though is I believe there is a very new ability for SharedArrayBuffer to be used in WebAssembly as "linear memory" which has a grow_memory operator. I would imagine taking advantage of this would be very difficult, if it is possible at all, and likely would not be supported in many browsers if it was.)


I have tried to implement it in a chained way, storing a SharedArrayBuffer object in another SharedArrayBuffer object, but the browser does not allow this.

Nope. You can only write numbers.

It might seem that you could use a number to index into a table of SharedArrayBuffers, and link them that way. But then you have to worry about how to share that table between threads--same problem.

So no matter what you do, whichever thread makes the decision to update the shared buffering structure will need to notify the others of the update somehow. For that notification to be able to transfer SharedArrayBuffers, it will have to use postMessage to do it.

Have you considered experimenting with allocating a larger SharedArrayBuffer to start with, and treat it like a circular buffer so that the main thread reads out of the writes the sub threads are doing, in a "producer/consumer" pattern?

If you insist on implementing resizes, you might consider having some portion of the buffer hold an indicator that it is "stale" and a new one must be requested from the thread that resized it. You'll have to control that with synchronization. If you make a small sample that does this, it would probably make a good technical article...and if you have trouble with the small sample, it would be a good basis for further questions here.

  • My program is a multi-threaded program. The main thread is constantly receiving network data, and the amount of data is relatively large, and the sub-threads are used to process the data. The received data is a 100-byte packet. Each time I receive a packet, I create a 100-byte Sharedarraybuffer and send it to the child thread via postMessage. The required function, but the main thread receives the data very fast, so it is necessary to frequently call the postmessage to notify the sub-thread, which will lead to high CPU usage, affecting the response speed of the main thread – 雨苓衡月 Oct 11 '18 at 03:01
  • So I was thinking, if sharedarraybuffer can grow dynamically, the received data is constantly appended at the end of the sharedarraybuffer, I only create a sharedarraybuffer, only notify the child thread once, so that the child thread can also access the data. It is like a pointer to C++. I have tried to implement it in a chained way, storing a shareddarraybuffer object in another sharedarraybuffer object, but the browser does not allow this. What advice do you have for this question? – 雨苓衡月 Oct 11 '18 at 03:01
  • @雨苓衡月 There's a button to EDIT your question to add details *(which is the preferred way, though don't use it as a way of asking a new or different question)*. I've gone ahead and done that for you, you can delete your comments. – HostileFork says dont trust SE Oct 11 '18 at 03:14
0

There is no way to resize, only copy via a typed array.

But no RAM is actually allocated, until the ram is actually used. Under Node.js (v14.14.0) you can see how the ram usage gradually increases as the buffer is filled or how it is basically instantly used if array.fill is used.

const sharedBuffer = new SharedArrayBuffer(512 * 1024 * 1024)
const array = new Uint8Array(sharedBuffer)

// array.fill(1) // Causes ram to be allocated right away
mgoetzke
  • 804
  • 7
  • 14
0

Perhaps look into using the grow() method of the SharedArrayBuffer.

Here is an example of how to increase the size:

const buffer = new SharedArrayBuffer(4, { maxByteLength: 10 });

if (buffer.growable) {
  buffer.grow(6);
}
Stanley Ulili
  • 702
  • 5
  • 7