Last time , as a preparation for talking about
ArrayBuffer and
SharedArrayBuffer , we looked at different approaches to memory management. As you must remember, the JS engine plays the role of a mediator in working with memory; however, new objects give the programmer some hand tools. What can it be needed for?

Javascript and memory management
Automatic memory management is a tradeoff between ease of development and additional system load. In some cases, this additional load leads to performance problems.
Automatic memory management simplifies development, but has an impact on program performance.')
For example, when you create a variable in JS, the engine needs to guess what type this variable will be and how it should be presented in memory. Such conjectures lead to the fact that the engine reserves more memory than it actually needs to store the variable. Depending on the type of data, the allocated memory may be 2-8 times more than necessary. This can lead to inefficient use of memory.
In addition to this, some patterns of creating and using JS objects can complicate garbage collection. If the programmer manages memory manually, he can avoid such problems by choosing strategies for allocating and freeing memory that meet the needs of a particular project.
In many cases, however, automatic memory management does not cause any particular problems. Most JS applications are not so demanding on performance to make programmers seriously think about manual memory management. And, in many cases, manual memory management can even have a negative impact on performance, at least on the programmer's productivity.
However, in those cases when the priority is the speed of the program, it makes sense to look towards the ArrayBuffer and the SharedArrayBuffer.
Manual memory management means more complete control over what happens in the code, allows you to achieve high performance solutions, but requires more mental work and increased attention to program design.How ArrayBuffer Works
In general, interfacing with ArrayBuffer seems to work with any other JS array. However, there is one important feature. It lies in the fact that when using ArrayBuffer, the programmer cannot put something like objects or lines into it. The only thing that is permissible to write to this array is bytes, which can be represented as numbers.
A regular array, on the left, can contain numbers, objects, strings, and so on. ArrayBuffer can only contain bytes.I would like to note that we, in fact, do not add bytes directly to ArrayBuffer. This object does not know what size the byte should be, or how different numbers should be converted to bytes.
ArrayBuffer can be represented as a sequence of zeros and ones written in one line. This object is not aware of where the borders of the elements are.
ArrayBuffer as a sequence of zeros and onesIn order for the raw data from ArrayBuffer to be perceived as something meaningful, to break the flow of zeros and units into blocks, you need to wrap it in a
DataView object or in a
typed array .
For example, as a wrapper, you can use an array of type
Int8Array , which will lead to the fact that what is stored in the ArrayBuffer will be split into 8-bit fragments.
The sequence of zeros and ones is divided into blocks of 8 bits.If we use the
Uint16Array typed array in such a situation, this will result in the contents of the ArrayBuffer being broken into fragments of 16 bits each, and this data will be perceived as unsigned integers.
The sequence of zeros and ones is divided into blocks of 16 bits.The same ArrayBuffer can serve as the basis for several wrappers. With this approach, the same operations on it will give different results.
For example, below it is shown that the first and second elements of the ArrayBuffer, which is accessed via an array of type Int8Array, differ from the first and second elements taken when working with an ArrayBuffer by means of the Uint16Array array. The same sequence of bits, when working with it through data structures of different types, looks different.
Access to the same ArrayBuffer using different wrappersIn such a situation, the ArrayBuffer is very similar to regular RAM. It emulates something like direct memory access, which is found in languages ​​like C.
You may be asking questions about why you need an additional level of abstraction over an ArrayBuffer, about whether it is better to give JS programmers direct memory access. Everything is done this way because direct memory access can be a source of security problems.
What is SharedArrayBuffer
In order to talk about what a SharedArrayBuffer is, you first need to understand how parallel code execution is done in JavaScript.
Parallelism allows you to speed up the program. This helps, for example, to perform data processing more quickly, or to respond to user interface events with less delay. The task that is planned to be parallelized must first be divided into subtasks.
In a typical JS application, all the work is done by the main thread. It resembles a full-cycle developer who is responsible for both JavaScript code and DOM, and the layout of the web page.
Anything that reduces the load on the main thread will have a beneficial effect on the performance of the application. In certain circumstances, using an ArrayBuffer can reduce the amount of work assigned to the main stream.
If you release the main thread from some of its normal work, represented by a stack of papers lying on the table, this will have a beneficial effect on the performance of the application.However, sometimes reducing the workload of the main thread is not enough. It happens that the main thread needs an assistant.
In most programming languages, certain tasks are usually performed in parallel using constructs called threads or processes. Their teamwork is reminiscent of how several people work on a project. If the tasks solved within the project are sufficiently independent of each other, they can be solved in parallel in several streams.
In JavaScript, this is implemented using the
Web Workers API . In particular, we are talking about an object of type
worker , which is a tool for working with background tasks. Background tasks in JS are slightly different from threads and processes from other languages. In particular, by default they do not have shared memory.
Now the work involved two streams. Piles of papers on the table of each of them are half the size of the previous figure. Each thread works with its own, not connected with another thread, memory area.All this means that in order to transfer some data from one stream to another, they must be copied into its memory area. This is done using the
postMessage function.
The postMessage function serializes the objects passed to it, transfers it to the background task for which they are intended, there they are deserialized and written to memory.
The postMessage function allows you to organize data exchange between threads.Transferring data between threads in this way is a rather slow process.
Working with some kinds of data, like the ones that are written in ArrayBuffer, you can do so-called memory transfer. In our example with two threads, this means the transfer to the second stream of a certain block of memory belonging to the first stream. After that, the second thread will be able to work with this memory block, and the first will lose access to it.
The division of memory between the two threads by transferring to the second thread a block of memory that previously belonged to the first thread. The first thread loses access to this memory, the second can work with it after that.This approach is applicable in some cases, but in many situations where the purpose of using multiple threads is high-performance data processing, you need a shared memory with which several processes can work simultaneously.
It is this opportunity that gives JS-developers SharedArrayBuffer.
The two threads have a common area of ​​memory that each of them can work with.Thanks to SharedArrayBuffer, both threads, both background tasks represented by worker objects, can read and write data in the same memory area.
This means that in this situation there are no additional costs of system resources for exchanging data between threads and delays that are inevitable when using the postMessage function. Both background tasks have the ability to work with memory as quickly as possible.
Instant access to memory from different streams, however, poses some dangers. In particular, this can lead to a state of race streams.
Race streams with access to the same memory areaWe will talk more about the state of race streams in the third part of this series of materials.
SharedArrayBuffer support
It is known that in the near future, the most popular browsers will be equipped with support for SharedArrayBuffer.
Browsers Welcome SharedArrayBufferSharedArrayBuffer support is already available in Safari (10.1). Next in line is Firefox and Chrome. They are supposed to acquire support for this new facility by the end of the summer. In Edge, most likely, the SharedArrayBuffer will appear in the fall.
Although SharedArrayBuffer will soon be supported by all major browsers, it is not expected that developers of ordinary applications will use it directly. Moreover, this is not recommended. It would be better to use special tools built on the basis of SharedArrayBuffer.
I would like to hope that the new features of SharedArrayBuffer will interest JS library developers, who will create simple and safe means, using which ordinary developers will be able to use SharedArrayBuffer in their projects.
In addition, since the SharedArrayBuffer object is a full part of the platform, it can be used in WebAssembly to implement streaming support. When this happens, JS programmers will have the opportunity to use concurrency abstractions that resemble those in other languages, such as Rust, which is known for reliable and convenient organization of multithreading.
Results
As you can see, SharedArrayBuffer is able to bring the interaction of parallel processes in JS to a new level, and, together with ArrayBuffer, give developers some possibilities for manual memory management.
Next time we will talk about tools that library developers can use when creating tools for multi-threaded work with data based on the SharedArrayBuffer. In particular, we will focus on the object JS
Atomics .
Dear readers! What options do you see in your ArrayBuffer and SharedArrayBuffer projects?