Hi,
I've been trying to find the most efficient way to pass JS TypeArrays to C/C++.
There are several ways to do this described in different places and I wanted to sort out the fastest one.
Many of the ways seem to incur some hidden copying that is difficult to find.
I wrote several approaches to the problem based on various sources and put them all together
here (live demo
in dev console here).
Here's a sample run (slightly formatted for discussion):
01: C sum: 630 ms
02: C sum, buffer: 174 ms
03: C sum_c: 171 ms
04: sum_str_cpy: 2701 ms
05: sum_str_ref: 2829 ms
06: sum_str_cpy, buffer: 2764 ms
07: sum_str_ref, buffer: 2693 ms
08: C sum heapBytes: 2117 ms
09: C sum heapBytes.buffer: 173 ms
10: C sum_c heapBytes.buffer: 171 ms
The results are quite interesting and not all make complete sense.
- First, there is a silent pessimization, when passing a TypedArray instead of its .buffer (see 1 vs. 2 above (also 8 vs. 9));
- Using std::string is much much more expensive than using char* (see 2-3 vs 4-7 above)
- There is no difference between using a std::string copy or reference. Surprising to me (see 4-7 above).
- There is no significant difference between using a JS Uint8Array and a heap allocated array!! (see 2-3 vs 9-10 above)
This was the most surprising to me as Alon explained that only heap allocated buffers can be passed w/o copying.
Either I am incurring a copy in both cases due to faulty usage in my examples (I would appreciate seeing the corrected code), or that regular JS typed-buffers are passed as-is without being copied (this would be great!).
Results are pretty much consistent across browsers and OSs.
Does this make sense?
Am I doing things wrong?
Thoughts?
Thanks,
Adi