From 5366e7d313e5f2aee43caeaff928285f858de6bd Mon Sep 17 00:00:00 2001 From: Tooru Fujisawa Date: Mon, 15 Nov 2021 00:00:48 +0900 Subject: [PATCH] Compress JSON data --- .gitignore | 5 ++- build.py | 33 ++++++++++---- index.html | 2 +- js/compare.js | 117 ++++++++++++++++++++++++++++++++++++++++++++++++- js/gunzip.wasm | Bin 0 -> 68025 bytes lib/Cargo.toml | 17 +++++++ lib/Makefile | 7 +++ lib/src/lib.rs | 14 ++++++ 8 files changed, 183 insertions(+), 12 deletions(-) create mode 100644 js/gunzip.wasm create mode 100644 lib/Cargo.toml create mode 100644 lib/Makefile create mode 100644 lib/src/lib.rs diff --git a/.gitignore b/.gitignore index 3948e4e60..be2b7209f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,7 @@ ecma262/ token.json venv/ node_modules/ -package-lock.json \ No newline at end of file +package-lock.json +lib/pkg +lib/target +lib/Cargo.lock \ No newline at end of file diff --git a/build.py b/build.py index 80a393af2..b49c8c246 100755 --- a/build.py +++ b/build.py @@ -4,6 +4,7 @@ import distutils import distutils.dir_util import glob +import gzip import json import os import re @@ -44,14 +45,31 @@ def read(path): with open(path, 'r') as in_file: return in_file.read() + def read_b(path): + with open(path, 'rb') as in_file: + return in_file.read() + @classmethod def read_json(cls, path): return json.loads(cls.read(path)) + @classmethod + def read_json_gz(cls, path): + print(path) + return json.loads(gzip.decompress(cls.read_b(path)).decode()) + def write(path, text): with open(path, 'w') as f: f.write(text) + def write_b(path, text): + with open(path, 'wb') as f: + f.write(text) + + @classmethod + def write_json_gz(cls, path, data): + cls.write_b(path, gzip.compress(json.dumps(data).encode())) + def write_formatted_json(path, data): text = json.dumps(data, indent=1, @@ -106,11 +124,11 @@ def pr_info_path(cls, prnum): @classmethod def sections_path(cls, sha, prnum=None): - return os.path.join(cls.rev_dir(sha, prnum), 'sections.json') + return os.path.join(cls.rev_dir(sha, prnum), 'sections.json.gz') @classmethod def parent_diff_path(cls, sha, prnum=None): - return os.path.join(cls.rev_dir(sha, prnum), 'parent_diff.json') + return os.path.join(cls.rev_dir(sha, prnum), 'parent_diff.json.gz') @classmethod def index_path(cls, sha, prnum=None): @@ -671,8 +689,7 @@ def __json(sha, prnum, skip_cache): data = SectionsExtractor.extract( FileUtils.read(Paths.index_path(sha, prnum))) - sections_json = json.dumps(data) - FileUtils.write(sections_path, sections_json) + FileUtils.write_json_gz(sections_path, data) return True @@ -693,18 +710,18 @@ def __parent_json(sha, prnum, parent, skip_cache): Logger.info(parent_diff_path) - to_json = FileUtils.read_json(sections_path) - from_json = FileUtils.read_json(parent_sections_path) + to_json = FileUtils.read_json_gz(sections_path) + from_json = FileUtils.read_json_gz(parent_sections_path) diff_json = SectionsComparator.compare(from_json, to_json) - result = json.dumps(diff_json) + result = gzip.compress(json.dumps(diff_json).encode()) if len(result) > 1024 * 1024: Logger.info('SKIP: {} is too large ({})'.format( parent_diff_path, len(result))) return False - FileUtils.write(parent_diff_path, result) + FileUtils.write_b(parent_diff_path, result) return True diff --git a/index.html b/index.html index a761516d3..0e7532d9b 100644 --- a/index.html +++ b/index.html @@ -9,7 +9,7 @@ - +
diff --git a/js/compare.js b/js/compare.js index 5ed15bc8c..a52ba017a 100644 --- a/js/compare.js +++ b/js/compare.js @@ -6,6 +6,108 @@ function sleep(t) { return new Promise(r => setTimeout(r, t)); } +// ==== BEGIN: copied and modified from wasm-pack binding ==== + +let wasm; + +let cachegetUint8Memory0 = null; +function getUint8Memory0() { + if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== wasm.memory.buffer) { + cachegetUint8Memory0 = new Uint8Array(wasm.memory.buffer); + } + return cachegetUint8Memory0; +} + +let WASM_VECTOR_LEN = 0; + +function passArray8ToWasm0(arg, malloc) { + const ptr = malloc(arg.length * 1); + getUint8Memory0().set(arg, ptr / 1); + WASM_VECTOR_LEN = arg.length; + return ptr; +} + +let cachegetInt32Memory0 = null; +function getInt32Memory0() { + if (cachegetInt32Memory0 === null || cachegetInt32Memory0.buffer !== wasm.memory.buffer) { + cachegetInt32Memory0 = new Int32Array(wasm.memory.buffer); + } + return cachegetInt32Memory0; +} + +function getArrayU8FromWasm0(ptr, len) { + return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len); +} + +/** + * @param {Uint8Array} data + * @returns {Uint8Array} + */ +async function decompress(data) { + if (!wasm) { + await init(); + } + + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + var ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc); + var len0 = WASM_VECTOR_LEN; + wasm.decompress(retptr, ptr0, len0); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var v1 = getArrayU8FromWasm0(r0, r1).slice(); + wasm.__wbindgen_free(r0, r1 * 1); + return v1; + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + } +} + +async function load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + + } catch (e) { + if (module.headers.get('Content-Type') != 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { + throw e; + } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + + } else { + return instance; + } + } +} + +async function init() { + const input = fetch("js/gunzip.wasm"); + + const imports = {}; + const { instance, module } = await load(await input, imports); + + wasm = instance.exports; + init.__wbindgen_wasm_module = module; + + return wasm; +} + +// ==== END ==== + // Insert list marker into list element. // // While creating diff, extra list element can be added. @@ -616,6 +718,17 @@ class Comparator { return response.json(); } + async getJSON_GZ(path) { + const response = await fetch(path); + if (!response.ok) { + return undefined; + } + const buf = await response.arrayBuffer(); + const arr = await decompress(new Uint8Array(buf)); + const decoder = new TextDecoder(); + return JSON.parse(decoder.decode(arr)); + } + populateLists() { this.populatePRs(this.prFilter); this.populateRevs(this.revFilter); @@ -1082,7 +1195,7 @@ class Comparator { let found = false; const toHash = this.toRev.value; if (!this.secAll.checked && this.getParentOf(toHash) === this.fromRev.value) { - const result = await this.getJSON(`./history/${toHash}/parent_diff.json`); + const result = await this.getJSON_GZ(`./history/${toHash}/parent_diff.json.gz`); if (result) { this.fromSecData = result.from; this.toSecData = result.to; @@ -1270,7 +1383,7 @@ class Comparator { } async getSecData(hash) { - return this.getJSON(`./history/${hash}/sections.json`); + return this.getJSON_GZ(`./history/${hash}/sections.json.gz`); } // Returns a string representation of section number+title that is comparable diff --git a/js/gunzip.wasm b/js/gunzip.wasm new file mode 100644 index 0000000000000000000000000000000000000000..1d422d390021a1175ba30c0afd6ee4c454e14d28 GIT binary patch literal 68025 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 literal 0 HcmV?d00001 diff --git a/lib/Cargo.toml b/lib/Cargo.toml new file mode 100644 index 000000000..932f34fff --- /dev/null +++ b/lib/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "wasm-gunzip" +version = "1.0.0" +authors = ["arai "] +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +wasm-bindgen = "0.2.78" +libflate= "1.0" + +[profile.release] +lto = true +codegen-units = 1 +opt-level = "z" diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 000000000..7092c4b71 --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,7 @@ +gunzip.wasm: src/lib.rs Cargo.toml + wasm-pack build --release --target web + wasm-snip \ + --snip-rust-panicking-code \ + --snip-rust-fmt-code \ + -o ../js/gunzip.wasm \ + pkg/wasm_gunzip_bg.wasm diff --git a/lib/src/lib.rs b/lib/src/lib.rs new file mode 100644 index 000000000..e342a48c2 --- /dev/null +++ b/lib/src/lib.rs @@ -0,0 +1,14 @@ +use libflate::gzip::Decoder; +use std::io::Read; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub fn decompress(data: &[u8]) -> Vec { + if let Ok(mut decoder) = Decoder::new(data) { + let mut result = Vec::new(); + if let Ok(_) = decoder.read_to_end(&mut result) { + return result + } + } + Vec::new() +}