Alright, so we discussed JavaScript can get your job done. But what about speed? Isn't Python or R supposed to be faster? Well, not necessarily. This graph compares execution speed for different array sizes on the x-axis where we are computing the sum of elements of a vector using a simple for loop. No surprise C is the fastest, but JavaScript closely follows with near-native speed because of the just-in-time compilers optimizing code at runtime. Meanwhile, Python and R struggle to keep up, especially when the array sizes grow.
We talked about speed, but what about WebAssembly? How does it compare? This chart shows performance for specific functions like the error function, exponential and logarithmic function. C is the fastest across the board, but notice that WebAssembly often underperforms plain JavaScript, especially for complex functions like exponential and logarithmic. For these kinds of one-off tasks, plain JavaScript performs well. But the whole story changes while applying the same operation to many elements in an array. Here we compare JavaScript against C, Wasm and WasmCopy for blast routines. In the first graph, Wasm performs much better as WasmCopy isn't worth it for routines such as DAXP because copying over the data adds a significant overhead when compared to the actual operation, which DAXP does. But for cases when operations are heavier, such as matrix multiplication in DGEMM, as we have in the second graph, the overhead for copying array data is less significant when compared with the actual operation. So there's a very small difference in the performance of Wasm and WasmCopy. So plain JS may not be the most efficient for these kind of operations, but we have instances where we can get accelerated performance in JavaScript run times.
In the first chart, we're evaluating the error function for multiple elements in a vector. With increasing vector sizes, calling a native add-on introduces significant overhead. So when we have small vector sizes, there's a significant overhead for adding a native add-on. But when the array sizes becomes large, that overhead becomes negligible and native add-ons show clear performance gains about three times faster for larger vectors. Now in the second chart, the second chart looks at the hardware accelerated blast using the Apple accelerate framework on macOS. Once again, there's a noticeable overhead for small vectors, but beyond 1000 elements, it drops significantly. Here native add-ons are around five times faster and the performance gap grows even more complex as we go towards more complex operations, such as matrix multiplication in case of DGEMM. So while JavaScript's just-in-time compilers are fast, they can deliver up to 25 or 50% of native code speed. In order to go even faster, we can leverage complementary technologies like Node.js native add-ons and hardware acceleration for a significant boost. So what is the solution that we can infer from all this? The solution is standard lib. Standard lib is a fundamental library for numerical computation on the web, similar to what we have numpy or scipy in Python. Some of its features include fancy indexing and by fancy indexing, we mean what we have in Python, the indexing where you can create and set arbitrary slices of array data and apply things like Boolean and integer array mask for filtering and data extraction. It also has blast, which is a collection of fundamental operations used for linear algebra, statistical analysis, image transformation, machine learning, and includes operations for matrix multiplication, manipulation, scaling, and transformation, some of which consist of examples such as DASM, which is used to compute the sum of absolute values or D.
Comments