#javascript
#язык JavaScript
Вопрос:
Моя цель-генерировать несжимаемые данные в Javascript, например /dev/urandom
Я использовал следующую команду со своего Mac, и я получил 31,5 Мб данных, которые невозможно сжать с помощью ZIP или RAR.
dd if=/dev/urandom of=file.txt bs=1048576 count=30
Но когда я пытаюсь создать несжимаемые данные в Javascript, например /dev/urandom
Это очень легко сжать в WinRAR. WinRAR сжат до менее чем 1 МБ. В Zip он сжимается до 30 МБ
Вот мой код
lt;!DOCTYPE htmlgt; lt;html lang="en"gt; lt;headgt; lt;meta charset="UTF-8"gt; lt;meta http-equiv="X-UA-Compatible" content="IE=edge"gt; lt;meta name="viewport" content="width=device-width, initial-scale=1.0"gt; lt;titlegt;How to generate Incompressible data in Javascript like /dev/urandomlt;/titlegt; lt;/headgt; lt;bodygt; lt;scriptgt; var ulDataSize = 30; //Mb var mData = new Float64Array(131072); var n = mData.length; for (var i = 0; i lt; n; i ) { mData[i] = Math.random()*9; } var uploadData = []; for (var i = 0; i lt; ulDataSize; i ) uploadData.push(mData); uploadData = new Blob(uploadData, { type: "application/octet-stream" }); function download(text, name, type) { var a = document.getElementById("a"); //var file = new Blob([text], {type: type}); a.href = URL.createObjectURL(uploadData); a.download = name; } lt;/scriptgt; lt;a href="" id="a"gt;click here to Download Incompressible datalt;/agt; lt;button onclick="download('file text', 'Incompressibledata.txt', 'text/plain')"gt; Generate Datalt;/buttongt; lt;/bodygt; lt;/htmlgt;
Комментарии:
1. Во-первых, попробуйте переключиться на uint8array и вместо этого использовать все значения.
2. Кроме того, в чем смысл повторного использования одних и тех же данных 30 раз? Таким образом, он явно поддается сжатию…
3. Потому что это не совсем случайно. Как отметил @user202729, вы повторяете блок случайных данных 30 раз, что недостаточно случайно
4. Это не те же самые данные. См. Math.random внутри forloop.
5. @user3642342 —
for (var i = 0; i lt; ulDataSize; i ) uploadData.push(mData);
явно повторно использует те же данныеulDataSize
, что и в комментариях выше.
Ответ №1:
Кроме того, ты повторяешь одни и те же данные 30 раз (который по своей сути является неслучайной), я не думаю, что Math.random() * 9
производит значения, во всем диапазоне битовых масок, что один и тот же элемент Float64Array
может содержать (хотя мой двоичной с плавающей запятой знаний не достаточно для обслуживания сомневаюсь, что с данными), что означает более битовых масок будет повторяться, уменьшения случайности.
Чтобы быть уверенным, я бы, вероятно, использовал a Uint8Array
со значениями в полном диапазоне от 0 до 255, с тех пор я уверен, что использую все битовые шаблоны; что-то вроде этого:
function download(name) { const blocks = Array.from( {length: 30}, () =gt; Uint8Array.from( {length: 1024 * 1024}, () =gt; Math.floor(Math.random() * 256) ) ); const blob = new Blob(blocks, {type: "application/octet-stream"}); const a = document.getElementById("a"); a.href = URL.createObjectURL(blob); a.download = name; }
Обратите внимание, что я удалил неиспользуемые name
и type
параметры.
Когда я использую это gzip
(инструмент, который у меня есть под рукой), размер результирующего файла не уменьшается (он увеличивается с 31 457 280 байт до 31 462 121 байта).
Это много вызовов Math.random()
, но нам в основном гарантировано, что мы полностью изучим доступные битовые шаблоны. Возможно, вы сможете сократить количество звонков с помощью a Uint16Array
или a Uint32Array
. Например:
const blockSize = (1024 * 1024) / 4; const blocks = Array.from( {length: 30}, () =gt; Uint32Array.from( {length: blockSize}, () =gt; Math.random() * 4294967296 ) );
Для меня gzip
все еще ничего не могло с этим поделать (тот же результат, что и выше), но на создание ушло чуть больше четверти времени.
Использование a Float64Array
не сработало (для меня), по-видимому Math.random
, не исследует весь спектр битовых шаблонов, возможных в 64-разрядном двоичном числе с плавающей запятой IEEE-754, и/или формат имеет (вероятно, небольшие) неиспользуемые диапазоны. Таким образом, 32-разрядные int могут быть лучшим компромиссом.
Комментарии:
1. это работает, ZIP и ZAR не имеют никакого значения. Потрясающе.
2. Но это требует больших затрат процессора. Занимаю секунду или две в моем i7 MBP. Можем ли мы сделать его немного более эффективным для процессора?. И все равно это Потрясающе!. Большое спасибо.
3. @user3642342 — Ну, это 30 миллионов звонков
Math.random
, не большой шок, если это займет какое-то время. Похоже, вы можете звонитьMath.random
меньше, используя aUint32Array
(см. Обновление). Все еще работал на меня, ваш пробег может отличаться.4. Да, теперь это в 2 раза быстрее.
5. @user3642342 — Ха, я получил не совсем 4 раза с моей стороны, но реализации различаются. 🙂