Module.HEAPU8.slice vs Module.HEAPU8.subarray

20 views
Skip to first unread message

Александр Гурьянов

unread,
Apr 20, 2020, 10:48:36 AM4/20/20
to emscripte...@googlegroups.com
Hi. I am doing worker backed for js-dos project, and now it pass all
tests that was made for default backend too. But I found inexplicable
behaviour. Worker process periodically sends updates for canvas. This
is code that I used:

```
Module.sendMessage = function (name, props) {
postMessage({
name,
props
});
};

...

#ifdef EMSCRIPTEN
EM_ASM(({
Module.frame_update_lines = [];
}));

for (uint32_t i = 0; i < count; ++i) {
uint32_t start = lines[i * 3];
uint32_t count = lines[i * 3 + 1];
uint32_t offset = lines[i * 3 + 2];
EM_ASM(({
Module.frame_update_lines.push({
start: $0,
heapu8: Module.HEAPU8.subarray($1, $1 + $2)
});
}), start, (char*) rgba + offset, sizeof(uint32_t) *
count * frameWidth);
}

EM_ASM(({
if (Module.frame_update_lines.length > 0) {
Module.sendMessage("ws-update-lines",
Module.frame_update_lines);
}
delete Module.frame_update_lines;
}));
#endif
```

So, message is array of rgba data that need to be drawn on canvas.
It's sort of dirty rects that need be updated.

When I run it results are terrible, both in Chrome and FF fps is near
11-12 FPS, when for non-worker version it is 55-60.

I tried a lot, and problem place as expected is sendMessage, lot of
time is spent here. BUT, by chance I tried to replace
Module.HEAPU8.subarray with Module.HEAPU8.slice and magic is happened.
With Module.HEAPU8.slice FPS for worker is 55-60 both in Chrome and
FF.

It's very good news for me, but I don't understand why I have this
performance boost. I thought that subarray should be faster then
slice, because as said it works on the same ArrayBuffer when slice is
copying it.

Why slice is faster then subarray?

Alon Zakai

unread,
Apr 20, 2020, 3:57:40 PM4/20/20
to emscripte...@googlegroups.com
I think what's going on here is that subarray() is another view on the same backing buffer. While slice() creates a new buffer for you.

For example:

> x = new Int8Array(10)
Int8Array [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
> x.buffer.byteLength
10
> x.subarray(1, 3).length
2
> x.subarray(1, 3).buffer.byteLength
10

So the length is small, but the buffer behind it is still the full original size.

> x.slice(1, 3).length
2
> x.slice(1, 3).buffer.byteLength
2

But a slice() has the right buffer size.

In other words, when you pass views on HEAP8, the browser is copying the entire buffer behind that, which is big - all of memory. You need to make a new buffer of the right size.

Note that you may be able to make this even more efficient using transfer,



--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-disc...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/emscripten-discuss/CAKOm%3DVES80yNV-mePExaQGrY-TRWe-c2%3DY89TMEOrdOj%3DFq-9w%40mail.gmail.com.
Reply all
Reply to author
Forward
0 new messages