{"id":319381,"date":"2021-03-11T09:01:01","date_gmt":"2021-03-11T09:01:01","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=319381"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=319381","title":{"rendered":"\u0420\u0430\u0437\u0433\u043e\u043d\u044f\u0435\u043c JS-\u043f\u0430\u0440\u0441\u0435\u0440 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e WebAssembly (\u0447\u0430\u0441\u0442\u044c 2: \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0438 \u0435\u0433\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438)"},"content":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<p>\u0412 <a href=\"https:\/\/habr.com\/ru\/post\/544824\/\">\u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438<\/a> \u043c\u044b \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043b\u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u043e\u0431\u043c\u0435\u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 JavaScript \u0438 WASM-\u043a\u043e\u0434\u043e\u043c. \u0412 \u044d\u0442\u043e\u043c \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0438 &#8212; \u043d\u0430\u043a\u043e\u043d\u0435\u0446-\u0442\u043e \u0437\u0430\u0439\u043c\u0435\u043c\u0441\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u043f\u0440\u0438\u043a\u043b\u0430\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0430\u0440\u0441\u0435\u0440\u0430.<\/p>\n<p>\u041c\u044b \u0432\u0435\u0434\u044c \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0438\u0448\u0435\u043c &#171;\u043f\u0440\u044f\u043c\u043e \u043d\u0430 \u0430\u0441\u0441\u0435\u043c\u0431\u043b\u0435\u0440\u0435&#187; &#8212; \u0437\u043d\u0430\u0447\u0438\u0442, \u0432\u0441\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u0443\u043f\u0435\u0440\u0431\u044b\u0441\u0442\u0440\u043e! \u041f\u0440\u0430\u0432\u0434\u0430 \u0432\u0435\u0434\u044c?<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/506\/c17\/542\/506c17542fb483c6706206679c4c00d0.jpg\" width=\"1450\" height=\"650\"><figcaption><\/figcaption><\/figure>\n<h2>\u041f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043d\u0430\u0438\u0432\u043d\u043e<\/h2>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0441\u0430\u043c\u044b\u0445 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 &#8212; \u043e\u043f\u0438\u0448\u0435\u043c, \u0433\u0434\u0435-\u043a\u0430\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043b\u0435\u0436\u0430\u0442\u044c \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<h4>JavaScript<\/h4>\n<ul>\n<li>\n<p>\u043f\u0435\u0440\u0432\u044b\u0435 12 * 8 \u0431\u0430\u0439\u0442 <code>[0x0000..0x005F]<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0434\u043b\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 <strong>64bit-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439<\/strong> \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 12 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u043a\u043b\u044e\u0447\u0435\u0439<\/p>\n<\/li>\n<li>\n<p>\u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u044d\u0442\u0438 \u043f\u043e\u043b\u044f \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u0430\u044f <code>parseBuffersWASM<\/code><\/p>\n<\/li>\n<li>\n<p>\u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 <strong>32bit-\u044f\u0447\u0435\u0439\u043a\u0435<\/strong> \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u0430\u043c\u044f\u0442\u0438 <code>[0xFFFC..0xFFFF]<\/code> \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 &#171;\u043a\u0443\u0440\u0441\u043e\u0440\u0430&#187; \u043f\u0430\u0440\u0441\u0435\u0440\u0430<\/p>\n<\/li>\n<li>\n<p><code>[0x10000..]<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u043c\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"javascript\">\/\/ ...   const data = readFileSync('buffers.txt');   memory.grow((data.byteLength &gt;&gt; 16) + 1);   \/\/ \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0446\u0438\u0438   const prj32 = new Uint32Array(memory.buffer);   const prj8 = new Uint8Array(memory.buffer);    \/\/ \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0440\u0430\u0437 \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e   const off = new WebAssembly.Global({value : 'i32', mutable : true}, 1 &lt;&lt; 16);    \/\/ \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0444\u0430\u0439\u043b\u0430, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u044f   data.copy(prj8, off.value);   \/\/ \u0434\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 '\\n' \u0443 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0441\u0442\u0440\u043e\u043a\u0438   prj8[off.value + data.length] = 0x0A;    const importObject = {     js : {       memory     , off     }   };    const instance = await WebAssembly.instantiate(module, importObject);   const parseBuffersWASM = instance.exports.parseBuffers;    \/\/ \u043d\u0430\u0431\u043e\u0440 \u043d\u0430\u0448\u0438\u0445 \u043a\u043b\u044e\u0447\u0435\u0439   const buffersKeys = ['shared-hit', 'shared-read', 'shared-dirtied', 'shared-written', 'local-hit', 'local-read', 'local-dirtied', 'local-written', 'temp-hit', 'temp-read', 'temp-dirtied', 'temp-written'];   const lnBK = buffersKeys.length;    const parseBuffers = () =&gt; {     \/\/ \u0437\u0430\u043d\u0443\u043b\u044f\u0435\u043c \u0432\u0441\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u0432\u044b\u0437\u043e\u0432\u043e\u043c     prj32.fill(0x0, 0, lnBK &lt;&lt; 1); \/\/ 32bit-\u044f\u0447\u0435\u0435\u043a \u0432 2 \u0440\u0430\u0437\u0430 \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c 64bit-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439     parseBuffersWASM();     let rv = {};     \/\/ \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043d\u0435\u043d\u0443\u043b\u0435\u0432\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043a\u043b\u044e\u0447\u0435\u0439     for (let i = 0, off = 0; i &lt; lnBK; i++) {       let val = prj32[off++] + prj32[off++] * 0x100000000;       if (val) {         rv[buffersKeys[i]] = val;       }     }     return rv;   }; \/\/ ...   \/\/ \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \"\u043a\u0443\u0440\u0441\u043e\u0440\u0430\" \u0432\u044b\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438\u0437 \u043f\u0430\u043c\u044f\u0442\u0438 0xFFFC   for (let lim = data.length + off.value; prj32[16383] &lt; lim; ) {     let obj = parseBuffers();   } \/\/ ...<\/code><\/pre>\n<h4>WASM<\/h4>\n<p>\u041f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u043c \u043d\u0430\u0448 JS-\u043a\u043e\u0434 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0430 \u0438\u0437 \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 &#171;\u043a\u0430\u043a \u0435\u0441\u0442\u044c&#187;:<\/p>\n<ul>\n<li>\n<p>\u0432\u0441\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0439 &#8212; \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0442\u0438\u043f\u0430 <code>off += off_v<\/code> \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u044b \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>WASM-HSM<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">(module   (import \"js\" \"memory\" (memory 1))    ;; \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \"\u043a\u0443\u0440\u0441\u043e\u0440\u0430\"   (global $off (import \"js\" \"off\") (mut i32))    ;; \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u043d\u0430\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c\u043e\u0435 \u0447\u0438\u0441\u043b\u043e   (global $val (mut i64)     (i64.const 0)   )    ;; \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 HSM   (global $state (mut i32)     (i32.const 0)   )   ;; \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435   (global $key (mut i32)     (i32.const 0)   )    ;; \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432   (func $setData     ;; buf[key &lt;&lt; 3] = val     (i64.store       (i32.shl         (global.get $key)         (i32.const 3)       )       (global.get $val)     )   )    ;; $off += $off_v   (func $step (param $off_v i32)     (global.set $off       (i32.add         (global.get $off)         (local.get $off_v)       )     )   )    ;; \u0440\u0430\u0437\u0431\u043e\u0440 \u0447\u0438\u0441\u043b\u0430 - \u043f\u043e\u0441\u0438\u043c\u0432\u043e\u043b\u044c\u043d\u043e   ;; ' ', ',' \u0438 '\\n' - \u0441\u0442\u043e\u043f-\u0441\u0438\u043c\u0432\u043e\u043b\u044b   (func $parseNumber     (local $ch i32)      (global.set $val       (i64.const 0)     )      (block       (loop         (local.set $ch           (i32.load8_u             (global.get $off)           )         )          ;; ch == ' '         (if           (i32.eq             (local.get $ch)             (i32.const 0x20)           )           (then             ;; off++             (call $step (i32.const 1))             (return)           )         )         ;; ch == ','         (if           (i32.eq             (local.get $ch)             (i32.const 0x2C)           )           (then             ;; off += 2             (call $step (i32.const 2))             (return)           )         )         ;; ch == '\\n'         (if           (i32.eq             (local.get $ch)             (i32.const 0x0A)           )           (then             ;; off++             (call $step (i32.const 1))             (return)           )         )          ;; val = val * 10 + (ch - 0x30)         (global.set $val           (i64.add             (i64.mul               (global.get $val)               (i64.const 10)             )             (i64.extend_i32_u               (i32.sub                 (local.get $ch)                 (i32.const 0x30) ;; '0'               )             )           )         )          ;; off++         (call $step (i32.const 1))          br 0 ;; do loop       )     )   )    ;; [state, off] = [state_v, off + off_v]   (func $iterate0 (param $state_v i32) (param $off_v i32)     ;; state = state_v     (global.set $state       (local.get $state_v)     )     ;; off += off_v     (call $step       (local.get $off_v)     )   )    ;; [key, off] = [state + state_v, off + off_v]   (func $iterate1 (param $state_v i32) (param $off_v i32)     ;; key = state + state_v     (global.set $key       (i32.add         (global.get $state)         (local.get $state_v)       )     )     ;; off += off_v     (call $step       (local.get $off_v)     )   )    ;; \u0430\u043d\u0430\u043b\u043e\u0433 String.charCodeAt   (func $charAtEq (param $char i32) (result i32)     (i32.eq       (i32.load8_u         (global.get $off)       ) ;; AL = line[$off] as unsigned       (local.get $char)     )   )    (func (export \"parseBuffers\")     ;; off += 'Buffers: '.length     (global.set $off       (i32.add         (global.get $off)         (i32.const 9)       )     )     ;; for (...)     (block       (loop         ;; case 's' \/\/ shared         (if           (call $charAtEq (i32.const 0x73))           (then             ;; $state = 0             ;; $off += 7             (call $iterate0               (i32.const 0)               (i32.const 7)             )             br 1 ;; \u0443\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u043d\u0430\u0447\u0430\u043b\u043e \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0446\u0438\u043a\u043b\u0430           )         )         ;; case 'l' \/\/ local         (if           (call $charAtEq (i32.const 0x6c))           (then             ;; $state = 4             ;; $off += 6             (call $iterate0               (i32.const 4)               (i32.const 6)             )             br 1           )         )         ;; case 't' \/\/ temp         (if           (call $charAtEq (i32.const 0x74))           (then             ;; $state = 8             ;; $off += 5             (call $iterate0               (i32.const 8)               (i32.const 5)             )             br 1           )         )          ;; case 'h' \/\/ hit         (if           (call $charAtEq (i32.const 0x68))           (then             ;; key = state + 0;             ;; $off += 4             (call $iterate1               (i32.const 0)               (i32.const 4)             )             ;;             call $parseNumber             call $setData             br 1           )         )         ;; case 'r' \/\/ read         (if           (call $charAtEq (i32.const 0x72))           (then             ;; key = state + 1;             ;; $off += 5             (call $iterate1               (i32.const 1)               (i32.const 5)             )             ;;             call $parseNumber             call $setData             br 1           )         )         ;; case 'd' \/\/ dirtied         (if           (call $charAtEq (i32.const 0x64))           (then             ;; key = state + 2;             ;; $off += 8             (call $iterate1               (i32.const 2)               (i32.const 8)             )             ;;             call $parseNumber             call $setData             br 1           )         )         ;; case 'w' \/\/ written         (if           (call $charAtEq (i32.const 0x77))           (then             ;; key = state + 3;             ;; $off += 8             (call $iterate1               (i32.const 3)               (i32.const 8)             )             ;;             call $parseNumber             call $setData             br 1           )         )          br 1       )     )      ;; \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435     (i32.store       (i32.const 0xFFFC)       (global.get $off)     )   ) )<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c\u2026<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ea2\/830\/536\/ea28305363e1667653016215ae52215a.gif\" width=\"218\" height=\"198\"><figcaption><\/figcaption><\/figure>\n<p><strong>76ms<\/strong> &#8212; \u043e\u0439, \u0438 \u044d\u0442\u043e \u0432\u043c\u0435\u0441\u0442\u043e 48ms \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e JS\u2026 \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f.<\/p>\n<h3>\u041f\u0440\u043e\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c<\/h3>\n<h4>\u041c\u0430\u0441\u043a\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/h4>\n<p>\u0410 \u0432\u0435\u0434\u044c \u043c\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 <strong>\u0432\u0441\u0435 96 \u0431\u0430\u0439\u0442<\/strong>, \u043a\u0443\u0434\u0430 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b, \u0437\u0430\u0442\u0438\u0440\u0430\u0435\u043c \u043d\u0443\u043b\u044f\u043c\u0438 &#8212; \u043f\u0440\u0438\u0447\u0435\u043c \u043d\u0435\u0432\u0430\u0436\u043d\u043e, \u043e\u0434\u043d\u043e, \u0434\u0432\u0430 \u0438\u043b\u0438 10 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043c\u044b \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u043b\u0438. \u0414\u0430 \u0435\u0449\u0435 \u0438 \u0447\u0438\u0442\u0430\u0435\u043c \u0438\u0445 \u0432\u0441\u0435!<\/p>\n<p>\u0410 \u0432\u0435\u0434\u044c \u0435\u0441\u043b\u0438 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u0438\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043b\u044e\u0447\u0438 \u0431\u044b\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u044b, \u0442\u043e \u0438 \u043e\u0442 \u0437\u0430\u043d\u0443\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f, \u0438 \u043e\u0442 \u0447\u0442\u0435\u043d\u0438\u044f \u043b\u0438\u0448\u043d\u0435\u0433\u043e. \u0421\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0432\u0435\u0441\u044c\u043c\u0430 \u043f\u0440\u043e\u0441\u0442\u043e &#8212; \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0438\u0437 WASM-\u043a\u043e\u0434\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441 \u0431\u0438\u0442\u043e\u0432\u043e\u0439 \u043c\u0430\u0441\u043a\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u043a\u043b\u044e\u0447\u0435\u0439:<\/p>\n<pre><code class=\"javascript\">  const buffersKeys = ['shared-hit', 'shared-read', 'shared-dirtied', 'shared-written', 'local-hit', 'local-read', 'local-dirtied', 'local-written', 'temp-hit', 'temp-read', 'temp-dirtied', 'temp-written'];    const parseBuffers = () =&gt; {     let mask = parseBuffersWASM();     let rv = {};     \/\/ \u0447\u0438\u0442\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u044f\u0447\u0435\u0439\u043a\u0438, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u043c \u0431\u0438\u0442\u0430\u043c \u043c\u0430\u0441\u043a\u0438      for (let i = 0; mask; mask &gt;&gt;= 1, i++) {       if (mask &amp; 1) {         let off = i &lt;&lt; 1;         rv[buffersKeys[i]] = prj32[off] + prj32[off + 1] * 0x100000000;       }     }     return rv;   };<\/code><\/pre>\n<pre><code class=\"javascript\">;; ...   (global $mask (mut i32)     (i32.const 0)   ) ;; ...   ;; \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043c\u0430\u0441\u043a\u0443 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435   (func $setData     ;; ...     ;; mask |= 1 &lt;&lt; key     (global.set $mask       (i32.or         (global.get $mask)         (i32.shl           (i32.const 1)           (global.get $key)         )       )     )   ) ;; ...   ;; \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043c\u0430\u0441\u043a\u0438   (func (export \"parseBuffers\") (result i32)     ;; mask = 0     (global.set $mask       (i32.const 0)     )     ;; ...      ;; \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043c\u0430\u0441\u043a\u0443     global.get $mask   )<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c &#8212; \u0443\u0436\u0435 <strong>54ms<\/strong>, \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u043f\u043b\u043e\u0442\u043d\u0443\u044e \u043f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u043b\u0438\u0441\u044c \u043a \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c\u0443 \u0432\u0440\u0435\u043c\u0435\u043d\u0438!<\/p>\n<h4>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0437\u043d\u0430\u043d\u0438\u044f \u043e \u0434\u0430\u043d\u043d\u044b\u0445<\/h4>\n<p>\u0415\u0441\u043b\u0438 \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0442\u043e \u0441\u0442\u0430\u043d\u0435\u0442 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0441\u0442\u0440\u043e\u043a \u0438\u043c\u0435\u044e\u0442 \u043b\u0438\u0431\u043e \u0432\u0438\u0434 <code>'shared hit=XXX'<\/code>, \u043b\u0438\u0431\u043e <code>'shared read=YYY'<\/code>, \u043b\u0438\u0431\u043e <code>'shared hit=XXX read=YYY'<\/code>, \u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0440\u0435\u0436\u0435 \u0447\u0442\u043e-\u0442\u043e \u0434\u0440\u0443\u0433\u043e\u0435 &#8212; \u0447\u0442\u043e \u0432\u043f\u043e\u043b\u043d\u0435 \u043b\u043e\u0433\u0438\u0447\u043d\u043e, \u0432\u0435\u0434\u044c \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u0443\u0437\u0435\u043b \u043f\u043b\u0430\u043d\u0430 \u0438\u043b\u0438 \u0447\u0438\u0442\u0430\u0435\u0442 \u0447\u0442\u043e-\u0442\u043e \u0438\u0437 \u043f\u0430\u043c\u044f\u0442\u0438, \u0438\u043b\u0438 \u0441 \u0434\u0438\u0441\u043a\u0430, \u0438\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0432\u0432\u0435\u0440\u0445 \u043f\u043e \u0434\u0435\u0440\u0435\u0432\u0443 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u0443\u044e \u0441\u0443\u043c\u043c\u0443 \u044d\u0442\u0438\u0445 \u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439.<\/p>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043c\u0430\u0441\u043a\u0438 <code>1, 2 \u0438\u043b\u0438 3<\/code>, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u043e \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u043d\u043e\u043c\u0443 \u043f\u0443\u0442\u0438:<\/p>\n<pre><code class=\"javascript\">  const m32to64 = 0x100000000;    const parseBuffers = () =&gt; {     let mask = parseBuffersWASM();     switch (mask) {       case 1:         return {'shared-hit'  : prj32[0] + prj32[1] * m32to64};       case 2:         return {'shared-read' : prj32[2] + prj32[3] * m32to64};       case 3:         return {           'shared-hit'  : prj32[0] + prj32[1] * m32to64         , 'shared-read' : prj32[2] + prj32[3] * m32to64         };       default:         let rv = {};         for (let i = 0; mask; mask &gt;&gt;= 1, i++) {           if (mask &amp; 1) {             let off = i &lt;&lt; 1;             rv[buffersKeys[i]] = prj32[off] + prj32[off + 1] * m32to64;           }         }         return rv;     }   }; <\/code><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 &#8212; <strong>44ms<\/strong>, \u0443\u0440\u0430! \u041c\u044b \u0443\u0436\u0435 \u043e\u043f\u0435\u0440\u0435\u0434\u0438\u043b\u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442. \u0410 \u0435\u0449\u0435 \u0431\u044b\u0441\u0442\u0440\u0435\u0435 &#8212; \u043c\u043e\u0436\u043d\u043e?<\/p>\n<h4>\u0423\u0441\u043b\u043e\u0432\u043d\u0430\u044f \u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/h4>\n<p>\u0417\u0430\u043c\u0435\u0442\u0438\u043c, \u0447\u0442\u043e \u0432 \u043d\u0430\u0448\u0435\u043c WASM-\u043a\u043e\u0434\u0435 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0435\u0441\u044c\u043c\u0430 \u043f\u043e\u0445\u043e\u0436\u0438\u0445 \u043a\u0443\u0441\u043a\u043e\u0432 \u0442\u0438\u043f\u0430 \u0442\u0430\u043a\u043e\u0433\u043e:<\/p>\n<pre><code class=\"javascript\">        ;; case 'w' \/\/ written         (if           (call $charAtEq (i32.const 0x77))           (then           ;; ...<\/code><\/pre>\n<p>\u041f\u0440\u0438\u0447\u0435\u043c, \u0435\u0441\u043b\u0438 \u043d\u0430\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435 \u0441 <code>'w'<\/code>, \u0442\u043e, \u0437\u043d\u0430\u0447\u0438\u0442, \u0443\u0436\u0435 6 \u043d\u0435\u0443\u0434\u0430\u0447\u043d\u044b\u0445 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0439 \u0434\u043e \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u043b\u0438 &#8212; \u0441 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430\u043c\u0438 <code>'s', 'l', 't', 'h', 'r', 'd'<\/code>.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0431\u043e\u0440\u0430, \u0432 WASM \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f <code>call_indirect<\/code>, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0430\u044f \u0432\u044b\u0437\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 <a href=\"https:\/\/developer.mozilla.org\/ru\/docs\/WebAssembly\/Understanding_the_text_format#%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%8B_webassembly\">\u0442\u0430\u0431\u043b\u0438\u0446\u0435\u0439<\/a>.<\/p>\n<p>\u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u0438 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u043e\u0435 \u0442\u0430\u043a\u043e\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0443\u044e <code>1<\/code>. <code>0<\/code> \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f-\u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0430, \u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0449\u0430\u044f \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u0435 \u043d\u0435\u043e\u043f\u043e\u0437\u043d\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0430. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u043a\u0430\u043a \u0440\u0430\u0437 \u0431\u0443\u0434\u0435\u0442 <code>'\\n'<\/code>, \u0441\u0438\u0433\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0449\u0430\u044f \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438:<\/p>\n<pre><code class=\"javascript\">;; ...   ;; \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u043a\u043e\u0441\u0432\u0435\u043d\u043d\u043e\u0439 \u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0439   (table 128 anyfunc)   (elem (i32.const 0)     $null ;; 00     $null ;;  1     ;; ...     $step_d ;;  4     $null ;;  5     $null ;;  6     $null ;;  7     $step_h ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $step_l ;;  C     $null ;;  D     $null ;;  E     $null ;;  F     $null ;; 70     $null ;;  1     $step_r ;;  2     $step_s ;;  3     $step_t ;;  4     $null ;;  5     $null ;;  6     $step_w ;;  7     $null ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $null ;;  C     $null ;;  D     $null ;;  E     $null ;;  F   )  ;; ...   (func $step_w (result i32) ;; written     ;; key = state + 3;     ;; $off += 8     (call $iterate1       (i32.const 3)       (i32.const 8)     )     ;;     call $parseNumber     call $setData      i32.const 1   ) ;; ...   (func (export \"parseBuffers\") (result i32)     ;; ...     ;; for (...)     (block       (loop         ;; if (table[line[off]]()) continue;         (br_if 0           (call_indirect (result i32)             (i32.load8_u               (global.get $off)             )           )         )         ;; break, end loop       )     ) ;; ...<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0438 \u0432\u0441\u0435\u0445 7 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">  ;; \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u043a\u043e\u0441\u0432\u0435\u043d\u043d\u043e\u0439 \u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0439   (table 128 anyfunc)   (elem (i32.const 0)     $null ;; 00     $null ;;  1     $null ;;  2     $null ;;  3     $null ;;  4     $null ;;  5     $null ;;  6     $null ;;  7     $null ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $null ;;  C     $null ;;  D     $null ;;  E     $null ;;  F     $null ;; 10     $null ;;  1     $null ;;  2     $null ;;  3     $null ;;  4     $null ;;  5     $null ;;  6     $null ;;  7     $null ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $null ;;  C     $null ;;  D     $null ;;  E     $null ;;  F     $null ;; 20     $null ;;  1     $null ;;  2     $null ;;  3     $null ;;  4     $null ;;  5     $null ;;  6     $null ;;  7     $null ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $null ;;  C     $null ;;  D     $null ;;  E     $null ;;  F     $null ;; 30     $null ;;  1     $null ;;  2     $null ;;  3     $null ;;  4     $null ;;  5     $null ;;  6     $null ;;  7     $null ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $null ;;  C     $null ;;  D     $null ;;  E     $null ;;  F     $null ;; 40     $null ;;  1     $null ;;  2     $null ;;  3     $null ;;  4     $null ;;  5     $null ;;  6     $null ;;  7     $null ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $null ;;  C     $null ;;  D     $null ;;  E     $null ;;  F     $null ;; 50     $null ;;  1     $null ;;  2     $null ;;  3     $null ;;  4     $null ;;  5     $null ;;  6     $null ;;  7     $null ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $null ;;  C     $null ;;  D     $null ;;  E     $null ;;  F     $null ;; 60     $null ;;  1     $null ;;  2     $null ;;  3     $step_d ;;  4     $null ;;  5     $null ;;  6     $null ;;  7     $step_h ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $step_l ;;  C     $null ;;  D     $null ;;  E     $null ;;  F     $null ;; 70     $null ;;  1     $step_r ;;  2     $step_s ;;  3     $step_t ;;  4     $null ;;  5     $null ;;  6     $step_w ;;  7     $null ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $null ;;  C     $null ;;  D     $null ;;  E     $null ;;  F   ) ;; ...   (func $null (result i32) ;; \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0430     i32.const 0   )    (func $step_s (result i32) ;; shared     ;; $state = 0     ;; $off += 7     (call $iterate0       (i32.const 0)       (i32.const 7)     )      i32.const 1   )    (func $step_l (result i32) ;; local     ;; $state = 4     ;; $off += 6     (call $iterate0       (i32.const 4)       (i32.const 6)     )      i32.const 1   )    (func $step_t (result i32) ;; temp     ;; $state = 8     ;; $off += 5     (call $iterate0       (i32.const 8)       (i32.const 5)     )      i32.const 1   )    (func $step_h (result i32) ;; hit     ;; key = state + 0;     ;; $off += 4     (call $iterate1       (i32.const 0)       (i32.const 4)     )     ;;     call $parseNumber     call $setData      i32.const 1   )    (func $step_r (result i32) ;; read     ;; key = state + 1;     ;; $off += 5     (call $iterate1       (i32.const 1)       (i32.const 5)     )     ;;     call $parseNumber     call $setData      i32.const 1   )    (func $step_d (result i32) ;; dirtied     ;; key = state + 2;     ;; $off += 8     (call $iterate1       (i32.const 2)       (i32.const 8)     )     ;;     call $parseNumber     call $setData      i32.const 1   )    (func $step_w (result i32) ;; written     ;; key = state + 3;     ;; $off += 8     (call $iterate1       (i32.const 3)       (i32.const 8)     )     ;;     call $parseNumber     call $setData      i32.const 1   )    (func (export \"parseBuffers\") (result i32)     ;; mask = 0     (global.set $mask       (i32.const 0)     )     ;; off += 'Buffers: '.length     (global.set $off       (i32.add         (global.get $off)         (i32.const 9)       )     )     ;; for (...)     (block       (loop         ;; if (table[line[off]]()) continue;         (br_if 0           (call_indirect (result i32)             (i32.load8_u               (global.get $off)             )           )         )         ;; break, end loop       )     )      ;; \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435     (i32.store       (i32.const 0xFFFC) ;; 16383 * 4       (global.get $off)     )     ;; \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043c\u0430\u0441\u043a\u0443     global.get $mask   )<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0430\u043a\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0442\u044b\u0433\u0440\u0430\u0442\u044c \u0435\u0449\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438 \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0432 <strong>40ms<\/strong> &#8212; \u043f\u043e\u0447\u0442\u0438 20% \u0432\u044b\u0438\u0433\u0440\u044b\u0448\u0430!<\/p>\n<h4>\u041e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u043c \u0443\u0441\u043b\u043e\u0432\u0438\u044f<\/h4>\n<p>\u0412\u044b\u0448\u0435 \u0443 \u043d\u0430\u0441 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043a\u043e\u0434, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0441\u0442\u043e\u043f-\u0441\u0438\u043c\u0432\u043e\u043b \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u0445\u0443\u0434\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0442\u0440\u0438\u0436\u0434\u044b &#8212; \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u043c \u044d\u0442\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0432 \u043e\u0434\u043d\u043e:<\/p>\n<pre><code class=\"javascript\">    (if       (i64.eq ;; n == 8         (local.get $n)         (i64.const 8)       )       (then         ;; off += 8         (call $step           (i32.const 8)         )       )       (else         ;; \u0448\u0430\u0433\u0430\u0435\u043c \u043d\u0430 n \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432         ;; ch == '\\n' || ch == ' ' =&gt; +1         ;; ch == ','               =&gt; +2         (call $step           (i32.add             (i32.wrap_i64               (local.get $n)             )             (i32.add               (i32.const 1)               (i64.eq                 (local.get $ch)                 (i64.const 0x2C)               )             )           )         )         (return)       )     ) <\/code><\/pre>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 CPU \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u0438\u043b\u044c\u043d\u043e \u043d\u0435 \u043b\u044e\u0431\u0438\u0442 \u0432\u0435\u0442\u0432\u043b\u0435\u043d\u0438\u044f, \u044d\u0442\u043e\u0442 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0442\u044b\u0433\u0440\u0430\u0442\u044c <strong>\u0435\u0449\u0435 2\u043c\u0441<\/strong>.<\/p>\n<h3>\u041f\u0440\u043e\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c (SWAR)<\/h3>\n<p>\u0412\u0441\u043f\u043e\u043c\u043d\u0438\u043c, \u0447\u0442\u043e \u043c\u044b \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0447\u0438\u0441\u043b\u043e &#171;\u043f\u043e\u0441\u0438\u043c\u0432\u043e\u043b\u044c\u043d\u043e&#187;, \u0430 \u0432\u0441\u0435 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043d\u043e\u0439 \u043e\u0442\u0440\u0430\u0441\u043b\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u043f\u0430\u0440\u0443 \u0434\u0435\u0441\u044f\u0442\u0438\u043b\u0435\u0442\u0438\u0439 \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e <strong>\u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0434\u043e \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0437\u0430 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e<\/strong> &#8212; \u0442\u043e \u0435\u0441\u0442\u044c <a href=\"https:\/\/ru.wikipedia.org\/wiki\/SIMD\">SIMD<\/a>-\u043f\u043e\u0434\u0445\u043e\u0434 \u0432 \u0447\u0438\u0441\u0442\u043e\u043c \u0432\u0438\u0434\u0435.<\/p>\n<p>\u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0442\u0435\u0445\u043d\u0438\u043a\u043e\u0439, \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0439 \u0432 <a href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/542640\/\">\u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u043e \u043f\u0430\u0440\u0441\u0438\u043d\u0433 double<\/a> &#8212; \u0437\u0430\u0447\u0435\u043c \u043f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0442\u044c &#171;\u043f\u043e\u0446\u0438\u0444\u0438\u0440\u043d\u043e&#187;, \u0435\u0441\u043b\u0438 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u0440\u0430\u0437\u0443 8 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u0441\u0447\u0438\u0442\u0430\u0432 \u0438\u0445 \u0432 \u0440\u0435\u0433\u0438\u0441\u0442\u0440.<\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u0442\u0443\u0442 \u0434\u0432\u0435:<\/p>\n<ul>\n<li>\n<p>\u043d\u0430\u0434\u043e \u0447\u0435\u0442\u043a\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0433\u0434\u0435\/\u0447\u0435\u043c \u0447\u0438\u0441\u043b\u043e \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f &#8212; \u043f\u0440\u043e\u0431\u0435\u043b\u043e\u043c (<code>0x20<\/code>), \u0437\u0430\u043f\u044f\u0442\u043e\u0439 (<code>0x2C<\/code>) \u0438\u043b\u0438 \u043a\u043e\u043d\u0446\u043e\u043c \u0441\u0442\u0440\u043e\u043a\u0438 (<code>0x0A<\/code>), \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043e\u0442 \u044d\u0442\u043e\u0433\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u0442, \u0447\u0435\u0440\u0435\u0437 \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0434\u0430\u043b\u044c\u0448\u0435 \u043d\u0430\u0434\u043e &#171;\u043f\u0435\u0440\u0435\u0448\u0430\u0433\u043d\u0443\u0442\u044c&#187;<\/p>\n<\/li>\n<li>\n<p>\u0447\u0438\u0441\u043b\u043e \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0443\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f \u0432 8 \u0431\u0430\u0439\u0442<\/p>\n<\/li>\n<\/ul>\n<h4>\u0423\u0437\u043d\u0430\u0435\u043c \u0434\u043b\u0438\u043d\u0443 \u0447\u0438\u0441\u043b\u0430<\/h4>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0447\u0438\u0441\u043b\u043e <code>'12345'<\/code> \u0441 \u043f\u0440\u043e\u0431\u0435\u043b\u043e\u043c \u043d\u0430 \u043a\u043e\u043d\u0446\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u0447\u0438\u0442\u0430\u043d\u043e \u0432 \u0440\u0435\u0433\u0438\u0441\u0442\u0440 \u043a\u0430\u043a <code>0x..203534333231 ...<\/code>. &#8212; \u0438 \u0442\u0443\u0442 \u043c\u043e\u0436\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043b\u044e\u0431\u043e\u0439 \u0438\u0437 \u0441\u0442\u043e\u043f-\u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043d\u0435 \u043f\u0440\u0435\u0432\u043e\u0441\u0445\u043e\u0434\u0438\u0442 <code>0x2F<\/code>, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u0446\u0438\u0444\u0440\u044b &#8212; \u0437\u0430\u0432\u0435\u0434\u043e\u043c\u043e \u043d\u0435 \u043c\u0435\u043d\u044c\u0448\u0435 <code>0x30<\/code>.<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0446\u0438\u0444\u0440 \u0432 \u0447\u0438\u0441\u043b\u0435 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043b\u0435\u0433\u043a\u043e:<\/p>\n<ul>\n<li>\n<p>\u0432\u0441\u0435 \u0446\u0438\u0444\u0440\u044b \u043f\u0440\u0438 \u043d\u0430\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043c\u0430\u0441\u043a\u0438 <code>&amp; 0x10<\/code> \u0434\u0430\u044e\u0442 \u043d\u0435\u043d\u0443\u043b\u0435\u0432\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u0430 \u0441\u0442\u043e\u043f-\u0441\u0438\u043c\u0432\u043e\u043b\u044b &#8212; \u043d\u0443\u043b\u0435\u0432\u043e\u0439<\/p>\n<\/li>\n<li>\n<p>\u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u0441 \u043a\u043e\u043d\u0446\u0430 \u043d\u0435\u043d\u0443\u043b\u0435\u0432\u043e\u0439 \u0431\u0430\u0439\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 <code>.ctz<\/code>, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0435\u0439 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043d\u0443\u043b\u0435\u0432\u044b\u0445 \u0431\u0438\u0442 &#171;\u0432 \u0445\u0432\u043e\u0441\u0442\u0435&#187; \u0447\u0438\u0441\u043b\u0430<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435\u0437\u043d\u0430\u0447\u0438\u043c\u043e\u0435 \u0434\u043b\u044f \u043d\u0430\u0441 \u0431\u0438\u0442\u043e\u0432\u043e\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u0431\u0430\u0439\u0442\u0430 (<code>ctz = 44<\/code>) \u0443\u0441\u0435\u0447\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0434\u0435\u043b\u0435\u043d\u0438\u0438 \u043d\u0430 8 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u0438\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0434\u0432\u0438\u0433\u0430<\/p>\n<\/li>\n<\/ul>\n<pre><code> #5        #4        #3        #2        #1        #0        - \u0441\u0442\u0430\u0440\u0448\u0438\u0439 &lt;- \u043c\u043b\u0430\u0434\u0448\u0438\u0439 0x20      0x35      0x34      0x33      0x32      0x31       = qword:i64 0010 0000 0011 0101 0011 0100 0011 0011 0011 0010 0011 0001 1101 1111 1100 1010 1100 0100 1100 1100 1100 1101 1100 1110  = not(qword) = qword ^ -1  0001 0000 0001 0000 0001 0000 0001 0000 0001 0000 0001 0000  = mask:i64  0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000  = not(qword) &amp; mask    ^                                                         = .ctz &gt;&gt; 3 = 5 byte<\/code><\/pre>\n<pre><code class=\"javascript\">    ;; \u043f\u043e\u0437\u0438\u0446\u0438\u044f \"\u043d\u0435\u0446\u0438\u0444\u0440\u043e\u0432\u043e\u0433\u043e\" \u0441\u0438\u043c\u0432\u043e\u043b\u0430     ;; n = ctz &gt;&gt; 3     (local.set $n       (i64.shr_u         (i64.ctz           (i64.and ;; digit mask == not(d) &amp; 0x10             (i64.xor ;; not(d) = d ^ -1               (local.get $qword)               (i64.const 0xFFFFFFFFFFFFFFFF)             )             (i64.const 0x1010101010101010) ;; digit mask           )         )         (i64.const 3)       )     )<\/code><\/pre>\n<h4>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0441\u0442\u043e\u043f-\u0441\u0438\u043c\u0432\u043e\u043b<\/h4>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043d\u0435\u0446\u0438\u0444\u0440\u043e\u0432\u043e\u0433\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0430, \u0441\u0434\u0432\u0438\u043d\u0435\u043c \u043d\u0430\u0448\u0435 \u0447\u0438\u0441\u043b\u043e \u043d\u0430 <code>n &lt;&lt; 3<\/code> \u0431\u0438\u0442 \u0432\u043f\u0440\u0430\u0432\u043e &#8212; \u0441\u0430\u043c\u044b\u0439 \u043c\u043b\u0430\u0434\u0448\u0438\u0439 \u0431\u0430\u0439\u0442 \u0438 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043a\u043e\u043c\u044b\u043c:<\/p>\n<pre><code class=\"javascript\">    ;; nb = n &lt;&lt; 3 \/\/ num bits     (local.set $nb       (i64.shl         (local.get $n)         (i64.const 3)       )     )      ;; ch = line[off + n]     (local.set $ch       (i32.wrap_i64         (i64.and           (i64.shr_u             (local.get $qword)             (local.get $nb)           )           (i64.const 0xFF) ;; \u043c\u043b\u0430\u0434\u0448\u0438\u0439 \u0431\u0430\u0439\u0442         )       )     ) <\/code><\/pre>\n<h4>\u0412\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c \u0447\u0438\u0441\u043b\u043e<\/h4>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u0447\u0442\u043e\u0431\u044b SWAR-\u0445\u0438\u043d\u0442 \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043a\u0430\u043a \u043d\u0430\u0434\u043e, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u0447\u0438\u0441\u043b\u0430 \u0432 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u044e:<\/p>\n<pre><code class=\"javascript\">    ;; top-align     ;; qword &lt;&lt;= 64 - nb     (local.set $qword       (i64.shl         (local.get $qword)         (i64.sub           (i64.const 64)           (local.get $nb)         )       )     ) <\/code><\/pre>\n<h4>SWAR-\u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u044f<\/h4>\n<pre><code class=\"javascript\">    ;; SWAR     ;; https:\/\/habr.com\/ru\/company\/ruvds\/blog\/542640\/      ;; v = ((v &amp; 0x0F0F0F0F0F0F0F0F) * 2561) &gt;&gt; 8     (local.set $qword       (i64.shr_u         (i64.mul           (i64.and             (local.get $qword)             (i64.const 0x0F0F0F0F0F0F0F0F)           )           (i64.const 2561)         )         (i64.const 8)       )     )     ;; v = ((v &amp; 0x00FF00FF00FF00FF) * 6553601) &gt;&gt; 16     (local.set $qword       (i64.shr_u         (i64.mul           (i64.and             (local.get $qword)             (i64.const 0x00FF00FF00FF00FF)           )           (i64.const 6553601)         )         (i64.const 16)       )     )     ;; v = ((v &amp; 0x0000FFFF0000FFFF) * 42949672960001) &gt;&gt; 32     (local.set $qword       (i64.shr_u         (i64.mul           (i64.and             (local.get $qword)             (i64.const 0x0000FFFF0000FFFF)           )           (i64.const 42949672960001)         )         (i64.const 32)       )     )<\/code><\/pre>\n<h4>\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f 64bit-\u0447\u0438\u0441\u0435\u043b<\/h4>\n<p>\u0412 \u043f\u043e\u0434\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0439, \u0447\u0438\u0441\u043b\u0430 \u0431\u0443\u0434\u0443\u0442 \u0443\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f \u0432 7 \u0437\u043d\u0430\u043a\u043e\u0432, \u0430 \u0438\u0437 8-\u0433\u043e \u043c\u044b \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043c \u0441\u0442\u043e\u043f-\u0441\u0438\u043c\u0432\u043e\u043b. \u041d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u043b\u0438\u043d\u043e\u0439 8 \u0438 \u0431\u043e\u043b\u0435\u0435 \u0437\u043d\u0430\u043a\u043e\u0432 \u0442\u043e\u0436\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0442\u0441\u044f &#8212; \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e, \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0446\u0438\u043a\u043b\u0430, \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u043c SWAR \u0434\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e 8-\u0441\u0438\u043c\u0432\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430.<\/p>\n<p>\u0422\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0434\u043e \u043d\u0435 \u0437\u0430\u0431\u044b\u0442\u044c, \u0447\u0442\u043e <strong>\u0432\u0442\u043e\u0440\u043e\u0439 \u0431\u043b\u043e\u043a \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c 0 \u0446\u0438\u0444\u0440<\/strong>, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u043f\u0435\u0440\u0432\u043e\u0433\u043e.<\/p>\n<p>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0432 <code>val<\/code> \u0447\u0438\u0441\u043b\u043e \u0438\u0437 \u043f\u0435\u0440\u0432\u044b\u0445 8 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u0430 \u0432 <code>qword<\/code> &#8212; \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0431\u043b\u043e\u043a\u0430. \u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u043d\u0430\u0434\u043e <code>val<\/code> \u0434\u043e\u043c\u043d\u043e\u0436\u0438\u0442\u044c \u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u0446\u0438\u0444\u0440 \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u0431\u043b\u043e\u043a\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0446\u0438\u0444\u0440:<\/p>\n<pre><code>'123456789' = '12345678' | '9' val = 12345678, qword = 9, n = 1 val = val * 10 ^ n + qword<\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0442\u044c \u043a\u043e\u044d\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442\u044b \u0434\u043e\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437, \u0437\u0430\u043d\u0435\u0441\u0435\u043c \u0438\u0445 \u0441\u0440\u0430\u0437\u0443 \u0432 \u043f\u0430\u043c\u044f\u0442\u044c \u043f\u043e \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u044e 128 (32 \u044f\u0447\u0435\u0439\u043a\u0438 \u043f\u043e 4 \u0431\u0430\u0439\u0442\u0430):<\/p>\n<pre><code class=\"javascript\">  \/\/ 10^N \u0434\u043b\u044f \u0434\u043e\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0432\u043e\u0433\u043e 32bit-\u0441\u0435\u0433\u043c\u0435\u043d\u0442\u0430   let pow10 = 1;   for (let i = 0; i &lt; 8; i++) {     prj32[i + 32] = pow10;     pow10 *= 10;   }<\/code><\/pre>\n<pre><code class=\"javascript\">    ;; val = val * memory[128 + (n &lt;&lt; 2)] + qword     (global.set $val       (i64.add         (i64.mul           (global.get $val)           (i64.extend_i32_u             (i32.load               (i32.add                 (i32.shl                   (i32.wrap_i64                     (local.get $n)                   )                   (i32.const 2)                 )                 (i32.const 128)               )             )           )         )         (local.get $qword)       )     )<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 buffers-test.js<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">const { readFileSync } = require('fs');  const fn = 'buffers-test';  const run = async () =&gt; {   const buffer = readFileSync(`${fn}.wasm`);   const module = await WebAssembly.compile(buffer);    const memory = new WebAssembly.Memory({initial : 1});    const data = readFileSync('buffers.txt');   memory.grow((data.byteLength &gt;&gt; 16) + 1);   const prj32 = new Uint32Array(memory.buffer);   const prj8 = new Uint8Array(memory.buffer);    \/\/ \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0440\u0430\u0437 \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e   const off = new WebAssembly.Global({value : 'i32', mutable : true}, 1 &lt;&lt; 16);    data.copy(prj8, off.value);   \/\/ \u0434\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 '\\n' \u0443 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0441\u0442\u0440\u043e\u043a\u0438   prj8[off.value + data.length] = 0x0A;    const importObject = {     js : {       memory     , off     }   };    \/\/ \u043f\u0440\u0435\u0434\u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c 10^N \u0432 \u0432\u0438\u0434\u0435 i64-\u044f\u0447\u0435\u0435\u043a \u0434\u043b\u044f \u0434\u043e\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430   let pow10 = 1;   for (let i = 0; i &lt; 8; i++) {     prj32[(i &lt;&lt; 1) + 32] = pow10;     pow10 *= 10;   }    const instance = await WebAssembly.instantiate(module, importObject);   const parseBuffersWASM = instance.exports.parseBuffers;    const buffersKeys = ['shared-hit', 'shared-read', 'shared-dirtied', 'shared-written', 'local-hit', 'local-read', 'local-dirtied', 'local-written', 'temp-hit', 'temp-read', 'temp-dirtied', 'temp-written'];   const m32to64 = 0x100000000;    const parseBuffers = () =&gt; {     let mask = parseBuffersWASM();     switch (mask) {       case 1:         return {'shared-hit'  : prj32[0] + prj32[1] * m32to64};       case 2:         return {'shared-read' : prj32[2] + prj32[3] * m32to64};       case 3:         return {           'shared-hit'  : prj32[0] + prj32[1] * m32to64         , 'shared-read' : prj32[2] + prj32[3] * m32to64         };       default:         let rv = {};         for (let i = 0; mask; mask &gt;&gt;= 1, i++) {           if (mask &amp; 1) {             let off = i &lt;&lt; 1;             rv[buffersKeys[i]] = prj32[off] + prj32[off + 1] * m32to64;           }         }         return rv;     }   };    const hrb = process.hrtime();   \/\/ -- 8&lt; --   \/\/ \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \"\u043a\u0443\u0440\u0441\u043e\u0440\u0430\" \u0432\u044b\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438\u0437 \u043f\u0430\u043c\u044f\u0442\u0438   for (let lim = data.length + off.value; prj32[16383] &lt; lim; ) {     let obj = parseBuffers();   }   \/\/ -- 8&lt; --   const hre = process.hrtime(hrb);   const usec = hre[0] * 1e+9 + hre[1];   console.log(usec); };  run();<\/code><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 buffers-test.wat<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">(module   (import \"js\" \"memory\" (memory 1))    ;; \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \"\u043a\u0443\u0440\u0441\u043e\u0440\u0430\"   (global $off (import \"js\" \"off\") (mut i32))    ;; \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435   (global $val (mut i64)     (i64.const 0)   )   (global $mask (mut i32)     (i32.const 0)   )   (global $state (mut i32)     (i32.const 0)   )   (global $key (mut i32)     (i32.const 0)   )    ;; \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u043a\u043e\u0441\u0432\u0435\u043d\u043d\u043e\u0439 \u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0439   (table 128 anyfunc)   (elem (i32.const 0)     $null ;; 00     $null ;;  1     $null ;;  2     $null ;;  3     $null ;;  4     $null ;;  5     $null ;;  6     $null ;;  7     $null ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $null ;;  C     $null ;;  D     $null ;;  E     $null ;;  F     $null ;; 10     $null ;;  1     $null ;;  2     $null ;;  3     $null ;;  4     $null ;;  5     $null ;;  6     $null ;;  7     $null ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $null ;;  C     $null ;;  D     $null ;;  E     $null ;;  F     $null ;; 20     $null ;;  1     $null ;;  2     $null ;;  3     $null ;;  4     $null ;;  5     $null ;;  6     $null ;;  7     $null ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $null ;;  C     $null ;;  D     $null ;;  E     $null ;;  F     $null ;; 30     $null ;;  1     $null ;;  2     $null ;;  3     $null ;;  4     $null ;;  5     $null ;;  6     $null ;;  7     $null ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $null ;;  C     $null ;;  D     $null ;;  E     $null ;;  F     $null ;; 40     $null ;;  1     $null ;;  2     $null ;;  3     $null ;;  4     $null ;;  5     $null ;;  6     $null ;;  7     $null ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $null ;;  C     $null ;;  D     $null ;;  E     $null ;;  F     $null ;; 50     $null ;;  1     $null ;;  2     $null ;;  3     $null ;;  4     $null ;;  5     $null ;;  6     $null ;;  7     $null ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $null ;;  C     $null ;;  D     $null ;;  E     $null ;;  F     $null ;; 60     $null ;;  1     $null ;;  2     $null ;;  3     $step_d ;;  4     $null ;;  5     $null ;;  6     $null ;;  7     $step_h ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $step_l ;;  C     $null ;;  D     $null ;;  E     $null ;;  F     $null ;; 70     $null ;;  1     $step_r ;;  2     $step_s ;;  3     $step_t ;;  4     $null ;;  5     $null ;;  6     $step_w ;;  7     $null ;;  8     $null ;;  9     $null ;;  A     $null ;;  B     $null ;;  C     $null ;;  D     $null ;;  E     $null ;;  F   )    ;; \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043c\u0430\u0441\u043a\u0443 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435   (func $setData     ;; buf[key &lt;&lt; 3] = val     (i64.store       (i32.shl         (global.get $key)         (i32.const 3)       )       (global.get $val)     )     ;; mask |= 1 &lt;&lt; key     (global.set $mask       (i32.or         (global.get $mask)         (i32.shl           (i32.const 1)           (global.get $key)         )       )     )   )    (func $step (param $off_v i32)     ;; $off += $off_v     (global.set $off       (i32.add         (global.get $off)         (local.get $off_v)       )     )   )    ;; \u0440\u0430\u0437\u0431\u043e\u0440 \u0447\u0438\u0441\u043b\u0430 - SWAR   (func $parseNumber     (local $qword i64)     (local $n i64)     (local $nb i64)     (local $ch i64)      (global.set $val       (i64.const 0)     )      ;; qword = line[off..+7]     (local.set $qword       (i64.load align=4         (global.get $off)       )     )      ;; \u043f\u043e\u0437\u0438\u0446\u0438\u044f \"\u043d\u0435\u0446\u0438\u0444\u0440\u043e\u0432\u043e\u0433\u043e\" \u0441\u0438\u043c\u0432\u043e\u043b\u0430     ;; n = num digits     (local.set $n       (i64.shr_u         (i64.ctz           (i64.and ;; digit mask == not(d) &amp; 0x10             (i64.xor               (local.get $qword)               (i64.const 0xFFFFFFFFFFFFFFFF)             )             (i64.const 0x1010101010101010) ;; digit mask           )         )         (i64.const 3)       )     )      ;; nb = n &lt;&lt; 3 \/\/ num bits     (local.set $nb       (i64.shl         (local.get $n)         (i64.const 3)       )     )      ;; ch = line[off + n]     (local.set $ch       (i64.and         (i64.shr_u           (local.get $qword)           (local.get $nb)         )         (i64.const 0xFF)       )     )      ;; top-align     ;; qword &lt;&lt;= 64 - nb     (local.set $qword       (i64.shl         (local.get $qword)         (i64.sub           (i64.const 64)           (local.get $nb)         )       )     )      ;; SWAR     ;; https:\/\/habr.com\/ru\/company\/ruvds\/blog\/542640\/      ;; v = ((v &amp; 0x0F0F0F0F0F0F0F0F) * 2561) &gt;&gt; 8     (local.set $qword       (i64.shr_u         (i64.mul           (i64.and             (local.get $qword)             (i64.const 0x0F0F0F0F0F0F0F0F)           )           (i64.const 2561)         )         (i64.const 8)       )     )     ;; v = ((v &amp; 0x00FF00FF00FF00FF) * 6553601) &gt;&gt; 16     (local.set $qword       (i64.shr_u         (i64.mul           (i64.and             (local.get $qword)             (i64.const 0x00FF00FF00FF00FF)           )           (i64.const 6553601)         )         (i64.const 16)       )     )     ;; v = ((v &amp; 0x0000FFFF0000FFFF) * 42949672960001) &gt;&gt; 32     (local.set $qword       (i64.shr_u         (i64.mul           (i64.and             (local.get $qword)             (i64.const 0x0000FFFF0000FFFF)           )           (i64.const 42949672960001)         )         (i64.const 32)       )     )      (global.set $val       (local.get $qword)     )      (if       (i64.eq ;; n == 8         (local.get $n)         (i64.const 8)       )       (then         ;; off += 8         (call $step           (i32.const 8)         )       )       (else         ;; \u0448\u0430\u0433\u0430\u0435\u043c \u043d\u0430 n \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432         ;; ch == '\\n' || ch == ' ' =&gt; +1         ;; ch == ','               =&gt; +2         (call $step           (i32.add             (i32.wrap_i64               (local.get $n)             )             (i32.add               (i32.const 1)               (i64.eq                 (local.get $ch)                 (i64.const 0x2C)               )             )           )         )         (return)       )     )      ;; qword = line[off..+7]     (local.set $qword       (i64.load         (global.get $off)       )     )      ;; n = (ctz - 4) \/ 8 == ctz &gt;&gt; 3 \/\/ num digits     (local.set $n       (i64.shr_u         (i64.ctz           (i64.and             (i64.xor ;; digit mask == not(d) &amp; 0x10               (local.get $qword)               (i64.const 0xFFFFFFFFFFFFFFFF)             )             (i64.const 0x1010101010101010) ;; digit mask           )         )         (i64.const 3)       )     )      ;; nb = n &lt;&lt; 3 \/\/ num bits     (local.set $nb       (i64.shl         (local.get $n)         (i64.const 3)       )     )      ;; ch = line[off + n]     (local.set $ch       (i64.and         (i64.shr_u           (local.get $qword)           (local.get $nb)         )         (i64.const 0xFF)       )     )      ;; if (n) ...     (if       (i32.wrap_i64         (local.get $n)       )       (then         ;; top-align         ;; qword &lt;&lt;= 64 - nb         (local.set $qword           (i64.shl             (local.get $qword)             (i64.sub               (i64.const 64)               (local.get $nb)             )           )         )          ;; SWAR         ;; https:\/\/habr.com\/ru\/company\/ruvds\/blog\/542640\/          ;; v = ((v &amp; 0x0F0F0F0F0F0F0F0F) * 2561) &gt;&gt; 8         (local.set $qword           (i64.shr_u             (i64.mul               (i64.and                 (local.get $qword)                 (i64.const 0x0F0F0F0F0F0F0F0F)               )               (i64.const 2561)             )             (i64.const 8)           )         )         ;; v = ((v &amp; 0x00FF00FF00FF00FF) * 6553601) &gt;&gt; 16         (local.set $qword           (i64.shr_u             (i64.mul               (i64.and                 (local.get $qword)                 (i64.const 0x00FF00FF00FF00FF)               )               (i64.const 6553601)             )             (i64.const 16)           )         )         ;; v = ((v &amp; 0x0000FFFF0000FFFF) * 42949672960001) &gt;&gt; 32         (local.set $qword           (i64.shr_u             (i64.mul               (i64.and                 (local.get $qword)                 (i64.const 0x0000FFFF0000FFFF)               )               (i64.const 42949672960001)             )             (i64.const 32)           )         )          ;; val = val * 10 ^ memory[128 + (n &lt;&lt; 3)]:i32 + qword         (global.set $val           (i64.add             (i64.mul               (global.get $val)               (i64.load align=8                 (i32.wrap_i64                   (i64.add                     (i64.shl                       (local.get $n)                       (i64.const 3)                     )                     (i64.const 128)                   )                 )               )             )             (local.get $qword)           )         )       )     )      ;; \u0448\u0430\u0433\u0430\u0435\u043c \u043d\u0430 n \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432     ;; ch == '\\n' || ch == ' ' =&gt; +1     ;; ch == ','               =&gt; +2     (call $step       (i32.add         (i32.wrap_i64           (local.get $n)         )         (i32.add           (i32.const 1)           (i64.eq             (local.get $ch)             (i64.const 0x2C)           )         )       )     )   )    ;; [state, off] = [state_v, off + off_v]   (func $iterate0 (param $state_v i32) (param $off_v i32)     ;; state = state_v     (global.set $state       (local.get $state_v)     )     ;; off += off_v     (call $step       (local.get $off_v)     )   )    ;; [key, off] = [state + state_v, off + off_v]   (func $iterate1 (param $state_v i32) (param $off_v i32)     ;; key = state + state_v     (global.set $key       (i32.add         (global.get $state)         (local.get $state_v)       )     )     ;; off += off_v     (call $step       (local.get $off_v)     )   )    (func $null (result i32)     i32.const 0   )    (func $step_s (result i32) ;; shared     ;; $state = 0     ;; $off += 7     (call $iterate0       (i32.const 0)       (i32.const 7)     )      i32.const 1   )    (func $step_l (result i32) ;; local     ;; $state = 4     ;; $off += 6     (call $iterate0       (i32.const 4)       (i32.const 6)     )      i32.const 1   )    (func $step_t (result i32) ;; temp     ;; $state = 8     ;; $off += 5     (call $iterate0       (i32.const 8)       (i32.const 5)     )      i32.const 1   )    (func $step_h (result i32) ;; hit     ;; key = state + 0;     ;; $off += 4     (call $iterate1       (i32.const 0)       (i32.const 4)     )     ;;     call $parseNumber     call $setData      i32.const 1   )    (func $step_r (result i32) ;; read     ;; key = state + 1;     ;; $off += 5     (call $iterate1       (i32.const 1)       (i32.const 5)     )     ;;     call $parseNumber     call $setData      i32.const 1   )    (func $step_d (result i32) ;; dirtied     ;; key = state + 2;     ;; $off += 8     (call $iterate1       (i32.const 2)       (i32.const 8)     )     ;;     call $parseNumber     call $setData      i32.const 1   )    (func $step_w (result i32) ;; written     ;; key = state + 3;     ;; $off += 8     (call $iterate1       (i32.const 3)       (i32.const 8)     )     ;;     call $parseNumber     call $setData      i32.const 1   )    (func (export \"parseBuffers\") (result i32)     ;; mask = 0     (global.set $mask       (i32.const 0)     )     ;; off += 'Buffers: '.length     (global.set $off       (i32.add         (global.get $off)         (i32.const 9)       )     )     ;; for (...)     (block       (loop         ;; if (table[line[off]]()) continue;         (br_if 0           (call_indirect (result i32)             (i32.load8_u               (global.get $off)             )           )         )         ;; break, end loop       )     )      ;; \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435     (i32.store       (i32.const 0xFFFC) ;; 16383 * 4       (global.get $off)     )     ;; \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043c\u0430\u0441\u043a\u0443     global.get $mask   ) )<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c &#8212; <strong>32ms<\/strong>!<\/p>\n<h3>\u0412\u043b\u0438\u044f\u043d\u0438\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u044e\u0449\u0435\u0433\u043e \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430<\/h3>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043d\u0430\u0448 \u043a\u043e\u0434 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c &#171;\u043d\u0430 \u043f\u043e\u0442\u043e\u043a\u0435&#187;, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043e\u043d \u043f\u0440\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u043c \u043f\u0440\u043e\u0433\u043e\u043d\u0435:<\/p>\n<pre><code class=\"javascript\">  \/\/ \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u0440\u043e\u0433\u043e\u043d   for (let lim = data.length + off.value; prj32[16383] &lt; lim; ) {     let obj = parseBuffers();   }    \/\/ \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0432 \u043d\u0430\u0447\u0430\u043b\u043e \u0444\u0430\u0439\u043b\u0430   off.value = 1 &lt;&lt; 16;   prj32[16383] = off.value;    const hrb = process.hrtime();   \/\/ -- 8&lt; --   \/\/ \u0437\u0430\u043c\u0435\u0440\u044f\u0435\u043c\u044b\u0439 \u0432\u0442\u043e\u0440\u043e\u0439 \u043f\u0440\u043e\u0433\u043e\u043d   for (let lim = data.length + off.value; prj32[16383] &lt; lim; ) {     let obj = parseBuffers();   }   \/\/ -- 8&lt; --<\/code><\/pre>\n<p>\u0425\u043c\u2026 \u043f\u043e\u0447\u0435\u043c\u0443-\u0442\u043e \u0441\u0442\u0430\u043b\u043e <strong>26ms<\/strong>. \u041f\u0440\u0438\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u043c\u0435\u043d\u044c\u0448\u0435, \u043d\u043e &#8212; \u043f\u043e\u0447\u0435\u043c\u0443? \u0414\u043b\u044f \u043e\u0442\u0432\u0435\u0442\u0430 \u043d\u0430 \u044d\u0442\u043e\u0442 \u0432\u043e\u043f\u0440\u043e\u0441 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u0431\u0430\u0439\u0442\u043a\u043e\u0434:<\/p>\n<pre><code class=\"bash\">node --print-wasm-code buffers-test.js &gt;_bytecode<\/code><\/pre>\n<p>\u0412 \u0442\u0435\u043b\u0435 \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0432\u0448\u0435\u0433\u043e\u0441\u044f \u0444\u0430\u0439\u043b\u0430 \u043f\u043e\u0438\u0449\u0435\u043c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e WASM-\u043a\u043e\u0434\u0430 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u0443 &#8212; \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, &#171;\u043c\u0430\u0441\u043a\u0443 \u0446\u0438\u0444\u0440&#187; <code>1010101010101010<\/code>.<\/p>\n<p>\u0427\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043e\u043d\u0430 \u043d\u0430\u0439\u0434\u0435\u0442\u0441\u044f \u0434\u0432\u0430\u0436\u0434\u044b:<\/p>\n<pre><code>--- WebAssembly code --- index: 2 kind: wasm function compiler: Liftoff ... 75  REX.W movq rdx,[rax+rcx*1]      ; rdx = qword  79  REX.W movq rax,rdx              ; rax = rdx 7c  REX.W xorq rax,0xff             ; rax = rax ^ 0xFF 80  REX.W movq rcx,1010101010101010 ; rcx = digit mask 8a  REX.W andq rax,rcx              ; rax = rax &amp; rcx 8d  REX.W bsfq rax,rax              ; rax = ctz(rax)<\/code><\/pre>\n<pre><code>--- WebAssembly code --- index: 2 kind: wasm function compiler: TurboFan ... 42  REX.W movq rbx,[rbx+r9*1]      ; rbx = qword  46  REX.W movq rdx,rbx             ; rdx = rbx 49  REX.W notq rdx                 ; rdx = not(rdx)    &lt;-- 4c  REX.W movq r9,1010101010101010 ; r9 = digit mask 56  REX.W andq rdx,r9              ; rdx = rdx &amp; r9 59  REX.W bsfq rdx,rdx             ; rdx = ctz(rdx)<\/code><\/pre>\n<p>\u041c\u044b \u0432\u0438\u0434\u0438\u043c \u0434\u0432\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0430\u0441\u0441\u0435\u043c\u0431\u043b\u0435\u0440\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0438 \u0442\u043e\u0433\u043e \u0436\u0435 WASM-\u043a\u043e\u0434\u0430. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u0440\u0435\u0434\u0438 WASM-\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 \u0431\u0430\u043d\u0430\u043b\u044c\u043d\u043e \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 <code>i32.not(v)<\/code>, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0432\u043f\u043e\u043b\u043d\u0435 <a href=\"https:\/\/github.com\/WebAssembly\/design\/issues\/379\">\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c<\/a> \u0447\u0435\u0440\u0435\u0437 <code>i32.xor(v, -1)<\/code>.<\/p>\n<p>\u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e \u043c\u044b \u0438 \u0432\u0438\u0434\u0438\u043c \u0432 \u043d\u0430\u0448\u0435\u043c \u0443\u0447\u0430\u0441\u0442\u043a\u0435 \u043a\u043e\u0434\u0430. \u041a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 Liftoff, \u0445\u043e\u0442\u044c \u0438 <a href=\"https:\/\/v8.dev\/blog\/liftoff\">\u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u043c<\/a>, \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u043b \u0442\u0430\u043a\u043e\u0439 \u0445\u0438\u043d\u0442 &#171;\u043f\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u043c\u0443&#187; \u0432 <code>xorq rax,0xff<\/code>, \u0430 TurboFan \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0431\u043e\u043b\u0435\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 <code>notq rdx<\/code>.<\/p>\n<p>\u0410 \u044d\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0430 \u0438\u0437 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u043c\u0435\u043b\u043a\u0438\u0445 \u0434\u0435\u0442\u0430\u043b\u0435\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0445\u043e\u0440\u043e\u0448\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0435\u0433\u043e \u0430\u0441\u0441\u0435\u043c\u0431\u043b\u0435\u0440\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0432 V8 &#8212; \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430, \u043d\u043e \u0438 \u0432\u0441\u0435-\u0442\u0430\u043a\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0434\u043e\u043b\u0438 \u0432\u0435\u0437\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043c\u0435\u0441\u0442\u043e SWAR-\u0445\u0438\u043d\u0442\u0430 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 SIMD-\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0432 WebAssembly, \u0438 \u0441\u0438\u043b\u044c\u043d\u043e \u043b\u0438 \u044d\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u043d\u0430\u043c.<\/p>\n<hr>\n<p>\u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/developer.mozilla.org\/ru\/docs\/WebAssembly\/Understanding_the_text_format#%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%8B_webassembly\">MDN: \u0422\u0430\u0431\u043b\u0438\u0446\u044b WebAssembly<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/542640\/\">\u041b\u0430\u0439\u0444\u0445\u0430\u043a: \u043a\u0430\u043a \u0441\u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442 double-\u043e\u0432 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0443<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/WebAssembly\/design\/issues\/379\">i32.neg and i32.not operations<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/v8.dev\/blog\/liftoff\">Liftoff: a new baseline compiler for WebAssembly in V8<\/a><\/p>\n<\/li>\n<\/ul>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/tensor\/blog\/545272\/\"> https:\/\/habr.com\/ru\/company\/tensor\/blog\/545272\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<p>\u0412 <a href=\"https:\/\/habr.com\/ru\/post\/544824\/\">\u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438<\/a> \u043c\u044b \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043b\u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u043e\u0431\u043c\u0435\u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 JavaScript \u0438 WASM-\u043a\u043e\u0434\u043e\u043c. \u0412 \u044d\u0442\u043e\u043c \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0438 &#8212; \u043d\u0430\u043a\u043e\u043d\u0435\u0446-\u0442\u043e \u0437\u0430\u0439\u043c\u0435\u043c\u0441\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u043f\u0440\u0438\u043a\u043b\u0430\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0430\u0440\u0441\u0435\u0440\u0430.<\/p>\n<p>\u041c\u044b \u0432\u0435\u0434\u044c \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0438\u0448\u0435\u043c &#171;\u043f\u0440\u044f\u043c\u043e \u043d\u0430 \u0430\u0441\u0441\u0435\u043c\u0431\u043b\u0435\u0440\u0435&#187; &#8212; \u0437\u043d\u0430\u0447\u0438\u0442, \u0432\u0441\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u0443\u043f\u0435\u0440\u0431\u044b\u0441\u0442\u0440\u043e! \u041f\u0440\u0430\u0432\u0434\u0430 \u0432\u0435\u0434\u044c?<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h2>\u041f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043d\u0430\u0438\u0432\u043d\u043e<\/h2>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0441\u0430\u043c\u044b\u0445 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 &#8212; \u043e\u043f\u0438\u0448\u0435\u043c, \u0433\u0434\u0435-\u043a\u0430\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043b\u0435\u0436\u0430\u0442\u044c \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<h4>JavaScript<\/h4>\n<ul>\n<li>\n<p>\u043f\u0435\u0440\u0432\u044b\u0435 12 * 8 \u0431\u0430\u0439\u0442 <code>[0x0000..0x005F]<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0434\u043b\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 <strong>64bit-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439<\/strong> \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 12 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u043a\u043b\u044e\u0447\u0435\u0439<\/p>\n<\/li>\n<li>\n<p>\u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u044d\u0442\u0438 \u043f\u043e\u043b\u044f \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u0430\u044f <code>parseBuffersWASM<\/code><\/p>\n<\/li>\n<li>\n<p>\u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 <strong>32bit-\u044f\u0447\u0435\u0439\u043a\u0435<\/strong> \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u0430\u043c\u044f\u0442\u0438 <code>[0xFFFC..0xFFFF]<\/code> \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 &#171;\u043a\u0443\u0440\u0441\u043e\u0440\u0430&#187; \u043f\u0430\u0440\u0441\u0435\u0440\u0430<\/p>\n<\/li>\n<li>\n<p><code>[0x10000..]<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u043c\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"javascript\">\/\/ ...   const data = readFileSync('buffers.txt');   memory.grow((data.byteLength &gt;&gt; 16) + 1);   \/\/ \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0446\u0438\u0438   const prj32 = new Uint32Array(memory.buffer);   const prj8 = new Uint8Array(memory.buffer);    \/\/ \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0440\u0430\u0437 \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e   const off = new WebAssembly.Global({value : 'i32', mutable : true}, 1 &lt;&lt; 16);    \/\/ \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0444\u0430\u0439\u043b\u0430, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u044f   data.copy(prj8, off.value);   \/\/ \u0434\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 '\\n' \u0443 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0441\u0442\u0440\u043e\u043a\u0438   prj8[off.value + data.length] = 0x0A;    const importObject = {     js : {       memory     , off     }   };    const instance = await WebAssembly.instantiate(module, importObject);   const parseBuffersWASM = instance.exports.parseBuffers;    \/\/ \u043d\u0430\u0431\u043e\u0440 \u043d\u0430\u0448\u0438\u0445 \u043a\u043b\u044e\u0447\u0435\u0439   const buffersKeys = ['shared-hit', 'shared-read', 'shared-dirtied', 'shared-written', 'local-hit', 'local-read', 'local-dirtied', 'local-written', 'temp-hit', 'temp-read', 'temp-dirtied', 'temp-written'];   const lnBK = buffersKeys.length;    const parseBuffers = () =&gt; {     \/\/ \u0437\u0430\u043d\u0443\u043b\u044f\u0435\u043c \u0432\u0441\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u0432\u044b\u0437\u043e\u0432\u043e\u043c     prj32.fill(0x0, 0, lnBK &lt;&lt; 1); \/\/ 32bit-\u044f\u0447\u0435\u0435\u043a \u0432 2 \u0440\u0430\u0437\u0430 \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c 64bit-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439     parseBuffersWASM();     let rv = {};     \/\/ \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043d\u0435\u043d\u0443\u043b\u0435\u0432\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043a\u043b\u044e\u0447\u0435\u0439     for (let i = 0, off = 0; i &lt; lnBK; i++) {       let val = prj32[off++] + prj32[off++] * 0x100000000;       if (val) {         rv[buffersKeys[i]] = val;       }     }     return rv;   }; \/\/ ...   \/\/ \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \"\u043a\u0443\u0440\u0441\u043e\u0440\u0430\" \u0432\u044b\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438\u0437 \u043f\u0430\u043c\u044f\u0442\u0438 0xFFFC   for (let lim = data.length + off.value; prj32[16383] &lt; lim; ) {     let obj = parseBuffers();   } \/\/ ...<\/code><\/pre>\n<h4>WASM<\/h4>\n<p>\u041f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u043c \u043d\u0430\u0448 JS-\u043a\u043e\u0434 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0430 \u0438\u0437 \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 &#171;\u043a\u0430\u043a \u0435\u0441\u0442\u044c&#187;:<\/p>\n<ul>\n<li>\n<p>\u0432\u0441\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0439 &#8212; \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0442\u0438\u043f\u0430 <code>off += off_v<\/code> \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u044b \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>WASM-HSM<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">(module   (import \"js\" \"memory\" (memory 1))    ;; \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \"\u043a\u0443\u0440\u0441\u043e\u0440\u0430\"   (global $off (import \"js\" \"off\") (mut i32))    ;; \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u043d\u0430\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c\u043e\u0435 \u0447\u0438\u0441\u043b\u043e   (global $val (mut i64)     (i64.const 0)   )    ;; \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 HSM   (global $state (mut i32)     (i32.const 0)   )   ;; \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435   (global $key (mut i32)     (i32.const 0)   )    ;; \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432   (func $setData     ;; buf[key &lt;&lt; 3] = val     (i64.store       (i32.shl         (global.get $key)         (i32.const 3)       )       (global.get $val)     )   )    ;; $off += $off_v   (func $step (param $off_v i32)     (global.set $off       (i32.add         (global.get $off)         (local.get $off_v)       )     )   )    ;; \u0440\u0430\u0437\u0431\u043e\u0440 \u0447\u0438\u0441\u043b\u0430 - \u043f\u043e\u0441\u0438\u043c\u0432\u043e\u043b\u044c\u043d\u043e   ;; ' ', ',' \u0438 '\\n' - \u0441\u0442\u043e\u043f-\u0441\u0438\u043c\u0432\u043e\u043b\u044b   (func $parseNumber     (local $ch i32)      (global.set $val       (i64.const 0)     )      (block       (loop         (local.set $ch           (i32.load8_u             (global.get $off)           )         )          ;; ch == ' '         (if           (i32.eq             (local.get $ch)             (i32.const 0x20)           )           (then             ;; off++             (call $step (i32.const 1))             (return)           )         )         ;; ch == ','         (if           (i32.eq             (local.get $ch)             (i32.const 0x2C)           )           (then             ;; off += 2             (call $step (i32.const 2))             (return)           )         )         ;; ch == '\\n'         (if           (i32.eq             (local.get $ch)             (i32.const 0x0A)           )           (then             ;; off++             (call $step (i32.const 1))             (return)           )         )          ;; val = val * 10 + (ch - 0x30)         (global.set $val           (i64.add             (i64.mul               (global.get $val)               (i64.const 10)             )             (i64.extend_i32_u               (i32.sub                 (local.get $ch)                 (i32.const 0x30) ;; '0'               )             )           )         )          ;; off++         (call $step (i32.const 1))          br 0 ;; do loop       )     )   )    ;; [state, off] = [state_v, off + off_v]   (func $iterate0 (param $state_v i32) (param $off_v i32)     ;; state = state_v     (global.set $state       (local.get $state_v)     )     ;; off += off_v     (call $step       (local.get $off_v)     )   )    ;; [key, off] = [state + state_v, off + off_v]   (func $iterate1 (param $state_v i32) (param $off_v i32)     ;; key = state + state_v     (global.set $key       (i32.add         (global.get $state)         (local.get $state_v)       )     )     ;; off += off_v     (call $step       (local.get $off_v)     )   )    ;; \u0430\u043d\u0430\u043b\u043e\u0433 String.charCodeAt   (func $charAtEq (param $char i32) (result i32)     (i32.eq       (i32.load8_u         (global.get $off)       ) ;; AL = line[$off] as unsigned       (local.get $char)     )   )    (func (export \"parseBuffers\")     ;; off += 'Buffers: '.length     (global.set $off       (i32.add         (global.get $off)         (i32.const 9)       )     )     ;; for (...)     (block       (loop         ;; case 's' \/\/ shared         (if           (call $charAtEq (i32.const 0x73))           (then             ;; $state = 0             ;; $off += 7             (call $iterate0               (i32.const 0)               (i32.const 7)             )             br 1 ;; \u0443\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u043d\u0430\u0447\u0430\u043b\u043e \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0446\u0438\u043a\u043b\u0430           )         )         ;; case 'l' \/\/ local         (if           (call $charAtEq (i32.const 0x6c))           (then             ;; $state = 4             ;; $off += 6             (call $iterate0               (i32.const 4)               (i32.const 6)             )             br 1           )         )         ;; case 't' \/\/ temp         (if           (call $charAtEq (i32.const 0x74))           (then             ;; $state = 8             ;; $off += 5             (call $iterate0               (i32.const 8)               (i32.const 5)             )             br 1           )         )          ;; case 'h' \/\/ hit         (if           (call $charAtEq (i32.const 0x68))           (then             ;; key = state + 0;             ;; $off += 4             (call $iterate1               (i32.const 0)               (i32.const 4)             )             ;;             call $parseNumber             call $setData             br 1           )         )         ;; case 'r' \/\/ read         (if           (call $charAtEq (i32.const 0x72))           (then             ;; key = state + 1;             ;; $off += 5             (call $iterate1               (i32.const 1)               (i32.const 5)             )             ;;             call $parseNumber             call $setData             br 1           )         )         ;; case 'd' \/\/ dirtied         (if           (call $charAtEq (i32.const 0x64))           (then             ;; key = state + 2;             ;; $off += 8             (call $iterate1               (i32.const 2)               (i32.const 8)             )             ;;             call $parseNumber             call $setData             br 1           )         )         ;; case 'w' \/\/ written         (if           (call $charAtEq (i32.const 0x77))           (then             ;; key = state + 3;             ;; $off += 8             (call $iterate1               (i32.const 3)               (i32.const 8)             )             ;;             call $parseNumber             call $setData             br 1           )         )          br 1       )     )      ;; \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435     (i32.store       (i32.const 0xFFFC)       (global.get $off)     )   ) )<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c\u2026<\/p>\n<figure class=\"\"><figcaption><\/figcaption><\/figure>\n<p><strong>76ms<\/strong> &#8212; \u043e\u0439, \u0438 \u044d\u0442\u043e \u0432\u043c\u0435\u0441\u0442\u043e 48ms \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e JS\u2026 \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f.<\/p>\n<h3>\u041f\u0440\u043e\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c<\/h3>\n<h4>\u041c\u0430\u0441\u043a\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/h4>\n<p>\u0410 \u0432\u0435\u0434\u044c \u043c\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 <strong>\u0432\u0441\u0435 96 \u0431\u0430\u0439\u0442<\/strong>, \u043a\u0443\u0434\u0430 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b, \u0437\u0430\u0442\u0438\u0440\u0430\u0435\u043c \u043d\u0443\u043b\u044f\u043c\u0438 &#8212; \u043f\u0440\u0438\u0447\u0435\u043c \u043d\u0435\u0432\u0430\u0436\u043d\u043e, \u043e\u0434\u043d\u043e, \u0434\u0432\u0430 \u0438\u043b\u0438 10 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043c\u044b \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u043b\u0438. \u0414\u0430 \u0435\u0449\u0435 \u0438 \u0447\u0438\u0442\u0430\u0435\u043c \u0438\u0445 \u0432\u0441\u0435!<\/p>\n<p>\u0410 \u0432\u0435\u0434\u044c \u0435\u0441\u043b\u0438 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u0438\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043b\u044e\u0447\u0438 \u0431\u044b\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u044b, \u0442\u043e \u0438 \u043e\u0442 \u0437\u0430\u043d\u0443\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f, \u0438 \u043e\u0442 \u0447\u0442\u0435\u043d\u0438\u044f \u043b\u0438\u0448\u043d\u0435\u0433\u043e. \u0421\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0432\u0435\u0441\u044c\u043c\u0430 \u043f\u0440\u043e\u0441\u0442\u043e &#8212; \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0438\u0437 WASM-\u043a\u043e\u0434\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441 \u0431\u0438\u0442\u043e\u0432\u043e\u0439 \u043c\u0430\u0441\u043a\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u043a\u043b\u044e\u0447\u0435\u0439:<\/p>\n<pre><code class=\"javascript\">  const buffersKeys = ['shared-hit', 'shared-read', 'shared-dirtied', 'shared-written', 'local-hit', 'local-read', 'local-dirtied', 'local-written', 'temp-hit', 'temp-read', 'temp-dirtied', 'temp-written'];    const parseBuffers = () =&gt; {     let mask = parseBuffersWASM();     let rv = {};     \/\/ \u0447\u0438\u0442\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u044f\u0447\u0435\u0439\u043a\u0438, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u043c \u0431\u0438\u0442\u0430\u043c \u043c\u0430\u0441\u043a\u0438      for (let i = 0; mask; mask &gt;&gt;= 1, i++) {       if (mask &amp; 1) {         let off = i &lt;&lt; 1;         rv[buffersKeys[i]] = prj32[off] + prj32[off + 1] * 0x100000000;       }     }     return rv;   };<\/code><\/pre>\n<pre><code class=\"javascript\">;; ...   (global $mask (mut i32)     (i32.const 0)   ) ;; ...   ;; \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043c\u0430\u0441\u043a\u0443 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435   (func $setData     ;; ...     ;; mask |= 1 &lt;&lt; key     (global.set $mask       (i32.or         (global.get $mask)         (i32.shl           (i32.const 1)           (global.get $key)         )       )     )   ) ;; ...   ;; \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043c\u0430\u0441\u043a\u0438   (func (export \"parseBuffers\") (result i32)     ;; mask = 0     (global.set $mask       (i32.const 0)     )     ;; ...      ;; \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043c\u0430\u0441\u043a\u0443     global.get $mask   )<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c &#8212; \u0443\u0436\u0435 <strong>54ms<\/strong>,<\/p>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-319381","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/319381","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=319381"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/319381\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=319381"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=319381"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=319381"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}