问题
FireFox 46.0.1: I am using 3rd-party (easyrtc) software to send 15KB chunks of Float32Arrays between peers. Easyrtc insists that the data be JSON-able. Unfortunately, JSON.stringify yields a string more than twice as long as the original data: 16384 bytes of data becomes a string of length 35755. Below is my test code followed by the console output. What if anything can I do to reduce the stringify'd size? Is there a way to send the values only (no keys)? Can I use the 'replacer' argument to send only the values, and if so, don't I need to use a replacer on the corresponding JSON.parse on the receiving end?
var g_testBufferNBytes = 4096 * 4;
var g_testBuffer = new ArrayBuffer(g_testBufferNBytes);
var g_testBufferView = new Float32Array(g_testBuffer);
console.log("array byte length " + g_testBuffer.byteLength);
console.log("view byte length " + g_testBufferView.byteLength);
var j = JSON.stringify(g_testBufferView);
console.log("j length " + j.length);
var newBuf = JSON.parse(j);
console.log("newBuf length " + Object.keys(newBuf).length);
CONSOLE: array byte length 16384 view byte length 16384 j length 35755 newBuf length 4096
回答1:
Yes
ES6: Assume that your data are in let f32 = g_testBufferView
(array Float32Array
) ) - whe can save it as JSON array in at leas 4 ways:
// code
let f32json = JSON.stringify(f32);
let f32jsonArr = JSON.stringify(Array.from(f32));
let f32base64 = btoa(String.fromCharCode(...(new Uint8Array(f32.buffer))));
let f32base128 = ... // not trivial, look below
// decode
let df32json = new Float32Array(Object.values(JSON.parse(f32json)));
let df32jsonArr = new Float32Array(JSON.parse(f32jsonArr));
let df32base64 = new Float32Array(new Uint8Array([...atob(f32base64)].map(c => c.charCodeAt(0))).buffer);
let df32base128 = ... // not trivial, look below
Note that Object.values
return values sorted by numeric keys (look here).
Here is working example. You can also use base128 do decode but I not use in this example (to not complicate it) - more details here.
If your Float32Array
- f32
has 4096 elements equals to 0.3
then:
f32
has 16384 bytes,f32json
(j
from your question) has 109483 bytes (which is >6x bigger thanf32
)f32jsonArr
has 81921 bytes (which is >5x bigger thanf32
)f32base64
has 21848 bytes(which is ~1.3x bigger thanf32
)f32base128
has 18725 bytes (whis is <1.15x bigger thanf32
) but chrome will send ~2x bigger request (depends on input data)
If your Float32Array
- f32
has 4096 elements equals integer from 1 to 9 then:
f32
has 16384 bytes - CONST,f32json
(j
from your question) has 35755 bytes (which is >2x bigger thanf32
)f32jsonArr
has 8193 bytes (which is 2x SMALLER (sic!) thanf32
)f32base64
has 21848 bytes - CONST (which is ~1.3x bigger thanf32
)f32base128
has 18725 bytes - CONST (whis is <1.15x bigger thanf32
) but chrome will send ~2x bigger request (depends on input data)
Conclusion
The smallest result which not depends of array values (result size is constant) we get for f32base64
~33% bigger than input array size. For f32base128
- it contains valid JSON (string) which is something about <15% bigger than input, but chrome during sending increase this size (look here - on 'update' section). So use f32base64
- this is probably the smallest JSON that you can get without more sophisticated methods.
来源:https://stackoverflow.com/questions/37330746/javascript-smallest-json-stringify-for-float32array