From f7b564dcd33170630e534372dd3b126a72daa5ef Mon Sep 17 00:00:00 2001 From: freestrings Date: Thu, 7 Mar 2019 18:44:06 +0900 Subject: [PATCH] =?UTF-8?q?NodeJs=EC=99=80=20=EA=B0=84=EB=8B=A8=ED=95=9C?= =?UTF-8?q?=20=EC=84=B1=EB=8A=A5=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- benches/bench.rs | 25 +-- benches/bench_bin/.gitignore | 4 + benches/bench_bin/Cargo.toml | 7 + benches/bench_bin/bench.sh | 8 + benches/bench_bin/src/main.rs | 21 +++ benches/bench_node_vs_rust.sh | 13 ++ benches/javascript/.gitignore | 2 + benches/javascript/bench.js | 108 ++++++++++++ benches/javascript/bench.sh | 2 + benches/javascript/package-lock.json | 244 +++++++++++++++++++++++++++ benches/javascript/package.json | 13 ++ benches/javascript/setup.sh | 5 + wasm/Cargo.toml | 2 +- wasm/node_modules/jsonpath-wasm | 1 + wasm/src/lib.rs | 4 + 16 files changed, 441 insertions(+), 20 deletions(-) create mode 100644 benches/bench_bin/.gitignore create mode 100644 benches/bench_bin/Cargo.toml create mode 100755 benches/bench_bin/bench.sh create mode 100644 benches/bench_bin/src/main.rs create mode 100755 benches/bench_node_vs_rust.sh create mode 100644 benches/javascript/.gitignore create mode 100644 benches/javascript/bench.js create mode 100755 benches/javascript/bench.sh create mode 100644 benches/javascript/package-lock.json create mode 100644 benches/javascript/package.json create mode 100755 benches/javascript/setup.sh create mode 120000 wasm/node_modules/jsonpath-wasm diff --git a/README.md b/README.md index 86c69e4..52bd299 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://travis-ci.org/freestrings/jsonpath.svg?branch=master)](https://travis-ci.org/freestrings/jsonpath) -`Rust` 버전 [JsonPath](https://goessner.net/articles/JsonPath/) 구현이다. Rust 구현과 동일한 기능을 `Webassembly` 로 제공하는 것 또한 목적이다. +`Rust` 버전 [JsonPath](https://goessner.net/articles/JsonPath/) 구현이다. Rust 구현과 동일한 기능을 `Webassembly` 로 제공하는 것도 목표. The `Rust` version is a [JsonPath](https://goessner.net/articles/JsonPath/) implementation. It is also aimed to provide the same functionality as `Webassembly` in Rust implementation. diff --git a/benches/bench.rs b/benches/bench.rs index 69538e5..cfe1957 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -1,12 +1,10 @@ #![feature(test)] -extern crate jsonpath; +extern crate jsonpath_lib as jsonpath; extern crate serde_json; extern crate test; use std::io::Read; - use serde_json::Value; - use self::test::Bencher; fn read_json(path: &str) -> String { @@ -17,22 +15,13 @@ fn read_json(path: &str) -> String { } #[bench] -fn bench_a(b: &mut Bencher) { - let string = read_json("./benches/data_array.json"); - let v: Value = serde_json::from_str(string.as_str()).unwrap(); +fn bench_reader(b: &mut Bencher) { + let string = read_json("./benches/example.json"); + let json: Value = serde_json::from_str(string.as_str()).unwrap(); + let mut reader = jsonpath::reader(json); b.iter(move || { - for _ in 1..1000 { - let _ = v.clone(); - } - }); -} - -#[bench] -fn bench_b(b: &mut Bencher) { - let string = read_json("./benches/data_array.json"); - b.iter(move || { - for _ in 1..1000 { - let _: Value = serde_json::from_str(string.as_str()).unwrap(); + for _ in 1..10000 { + let _ = reader("$.store").unwrap(); } }); } \ No newline at end of file diff --git a/benches/bench_bin/.gitignore b/benches/bench_bin/.gitignore new file mode 100644 index 0000000..bbcdd09 --- /dev/null +++ b/benches/bench_bin/.gitignore @@ -0,0 +1,4 @@ +/target +**/*.rs.bk +Cargo.lock +bin/ \ No newline at end of file diff --git a/benches/bench_bin/Cargo.toml b/benches/bench_bin/Cargo.toml new file mode 100644 index 0000000..c11ab6b --- /dev/null +++ b/benches/bench_bin/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bench_bin" +version = "0.1.0" + +[dependencies] +jsonpath_lib = {path = "../../"} +serde_json = { version = "1.0", features = ["preserve_order"] } \ No newline at end of file diff --git a/benches/bench_bin/bench.sh b/benches/bench_bin/bench.sh new file mode 100755 index 0000000..96a63eb --- /dev/null +++ b/benches/bench_bin/bench.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e + +if [ -d "target/release" ]; then + ./target/release/bench_bin +else + echo "빌드먼저" +fi \ No newline at end of file diff --git a/benches/bench_bin/src/main.rs b/benches/bench_bin/src/main.rs new file mode 100644 index 0000000..9eee77c --- /dev/null +++ b/benches/bench_bin/src/main.rs @@ -0,0 +1,21 @@ +extern crate jsonpath_lib as jsonpath; +extern crate serde_json; + +use serde_json::Value; +use std::io::Read; + +fn read_json(path: &str) -> String { + let mut f = std::fs::File::open(path).unwrap(); + let mut contents = String::new(); + f.read_to_string(&mut contents).unwrap(); + contents +} + +fn main() { + let string = read_json("../example.json"); + let json: Value = serde_json::from_str(string.as_str()).unwrap(); + let mut reader = jsonpath::reader(json); + for _ in 1..100000 { + let _ = reader(r#"$..book[?(@.price<30 && @.category=="fiction")]"#).unwrap(); + } +} diff --git a/benches/bench_node_vs_rust.sh b/benches/bench_node_vs_rust.sh new file mode 100755 index 0000000..c6747bc --- /dev/null +++ b/benches/bench_node_vs_rust.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -e +DIR="$(pwd)" + +cd "${DIR}"/bench_bin && cargo build --release + +printf "\n\n$..book[?(@.price<30 && @.category=="fiction")] (loop 100,000)" +printf "\n\n" + +echo "Rust: " && time ./bench.sh +printf "\n" +cd "${DIR}"/javascript && echo "NodeJs: " && time ./bench.sh diff --git a/benches/javascript/.gitignore b/benches/javascript/.gitignore new file mode 100644 index 0000000..f06235c --- /dev/null +++ b/benches/javascript/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist diff --git a/benches/javascript/bench.js b/benches/javascript/bench.js new file mode 100644 index 0000000..60fde85 --- /dev/null +++ b/benches/javascript/bench.js @@ -0,0 +1,108 @@ +let json = { + "store": { + "book": [ + { + "category": "reference", + "author": "Nigel Rees", + "title": "Sayings of the Century", + "price": 8.95 + }, + { + "category": "fiction", + "author": "Evelyn Waugh", + "title": "Sword of Honour", + "price": 12.99 + }, + { + "category": "fiction", + "author": "Herman Melville", + "title": "Moby Dick", + "isbn": "0-553-21311-3", + "price": 8.99 + }, + { + "category": "fiction", + "author": "J. R. R. Tolkien", + "title": "The Lord of the Rings", + "isbn": "0-395-19395-8", + "price": 22.99 + } + ], + "bicycle": { + "color": "red", + "price": 19.95 + } + }, + "expensive": 10 +}; + +const jp = require('jsonpath'); +const jpw = require('jsonpath-wasm'); +const Benchmark = require('benchmark'); + +function compareJsonpath(path) { + let r1 = jp.query(json, path); + let r2 = jpw.read(json, path); + + let template = jpw.compile(path); + + var suite = new Benchmark.Suite; + + suite.add('jp', function() { + jp.query(json, path); + }) + .add('jpw', function() { + template(json); + }) + .on('cycle', function(event) { + console.log(String(event.target)); + }) + .on('complete', function() { + console.log('Fastest is ' + this.filter('fastest').map('name')); + console.log('Slowest is ' + this.filter('slowest').map('name')); + }) + .run({ 'async': true }); +} + +function compareEmptyFunction() { + var suite = new Benchmark.Suite; + + suite.add('js', function() { + }) + .add('rust', function() { + jpw.testa(); + }) + .on('cycle', function(event) { + console.log(String(event.target)); + }) + .on('complete', function() { + console.log('Fastest is ' + this.filter('fastest').map('name')); + console.log('Slowest is ' + this.filter('slowest').map('name')); + }) + .run({}); +} + +function jsonpathOnly() { + for(var i = 0; i < 100000 ; i++) { + let _ = jp.query(json, '$..book[?(@.price<30 && @.category==\"fiction\")]'); + } +} + +if(process.argv.length < 3) { + let functions = ['', 'compareJsonpath', 'compareEmptyFunction', 'jsonpathOnly']; + console.log("node bench.js", functions.join("\n\t|")); + return; +} + +let functionName = process.argv[2]; + +switch (functionName) { + case 'compareJsonpath': + compareJsonpath('$..book[?(@.price<30 && @.category==\"fiction\")]'); + break; + case 'compareEmptyFunction': + compareEmptyFunction(); + break; + default: + jsonpathOnly(); +} \ No newline at end of file diff --git a/benches/javascript/bench.sh b/benches/javascript/bench.sh new file mode 100755 index 0000000..21b545b --- /dev/null +++ b/benches/javascript/bench.sh @@ -0,0 +1,2 @@ +#!/bin/bash +node bench.js jsonpathOnly \ No newline at end of file diff --git a/benches/javascript/package-lock.json b/benches/javascript/package-lock.json new file mode 100644 index 0000000..f1ade82 --- /dev/null +++ b/benches/javascript/package-lock.json @@ -0,0 +1,244 @@ +{ + "name": "jsonpath-benches", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "JSONSelect": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.4.0.tgz", + "integrity": "sha1-oI7cxn6z/L6Z7WMIVTRKDPKCu40=" + }, + "benchmark": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz", + "integrity": "sha1-CfPeMckWQl1JjMLuVloOvzwqVik=", + "requires": { + "lodash": "^4.17.4", + "platform": "^1.3.3" + } + }, + "cjson": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cjson/-/cjson-0.2.1.tgz", + "integrity": "sha1-c82KrWXZ4VBfmvF0TTt5wVJ2gqU=" + }, + "colors": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", + "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "ebnf-parser": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/ebnf-parser/-/ebnf-parser-0.1.10.tgz", + "integrity": "sha1-zR9rpHfFY4xAyX7ZtXLbW6tdgzE=" + }, + "escodegen": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-0.0.21.tgz", + "integrity": "sha1-U9ZSz6EDA4gnlFilJmxf/HCcY8M=", + "requires": { + "esprima": "~1.0.2", + "estraverse": "~0.0.4", + "source-map": ">= 0.1.2" + }, + "dependencies": { + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=" + } + } + }, + "esprima": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz", + "integrity": "sha1-dqD9Zvz+FU/SkmZ9wmQBl1CxZXs=" + }, + "estraverse": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-0.0.4.tgz", + "integrity": "sha1-AaCTLf7ldGhKWYr1pnw7+bZCjbI=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "jison": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/jison/-/jison-0.4.13.tgz", + "integrity": "sha1-kEFwfWIkE2f1iDRTK58ZwsNvrHg=", + "requires": { + "JSONSelect": "0.4.0", + "cjson": "~0.2.1", + "ebnf-parser": "~0.1.9", + "escodegen": "0.0.21", + "esprima": "1.0.x", + "jison-lex": "0.2.x", + "lex-parser": "~0.1.3", + "nomnom": "1.5.2" + }, + "dependencies": { + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=" + } + } + }, + "jison-lex": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/jison-lex/-/jison-lex-0.2.1.tgz", + "integrity": "sha1-rEuBXozOUTLrErXfz+jXB7iETf4=", + "requires": { + "lex-parser": "0.1.x", + "nomnom": "1.5.2" + } + }, + "jsonpath": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.0.1.tgz", + "integrity": "sha512-HY5kSg82LHIs0r0h9gYBwpNc1w1qGY0qJ7al01W1bJltsN2lp+mjjA/a79gXWuvD6Xf8oPkD2d5uKMZQXTGzqA==", + "requires": { + "esprima": "1.2.2", + "jison": "0.4.13", + "static-eval": "2.0.2", + "underscore": "1.7.0" + } + }, + "jsonpath-wasm": { + "version": "0.1.1" + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lex-parser": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/lex-parser/-/lex-parser-0.1.4.tgz", + "integrity": "sha1-ZMTwJfF/1Tv7RXY/rrFvAVp0dVA=" + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "nomnom": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.5.2.tgz", + "integrity": "sha1-9DRUSKhTz71cDSYyDyR3qwUm/i8=", + "requires": { + "colors": "0.5.x", + "underscore": "1.1.x" + }, + "dependencies": { + "underscore": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.1.7.tgz", + "integrity": "sha1-QLq4S60Z0jAJbo1u9ii/8FXYPbA=" + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "platform": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz", + "integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "optional": true + }, + "static-eval": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", + "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==", + "requires": { + "escodegen": "^1.8.1" + }, + "dependencies": { + "escodegen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", + "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + } + } + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=" + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + } + } +} diff --git a/benches/javascript/package.json b/benches/javascript/package.json new file mode 100644 index 0000000..cb38774 --- /dev/null +++ b/benches/javascript/package.json @@ -0,0 +1,13 @@ +{ + "name": "jsonpath-benches", + "version": "1.0.0", + "main": "bench.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "dependencies": { + "jsonpath": "*", + "jsonpath-wasm": "*", + "benchmark": "*" + } +} diff --git a/benches/javascript/setup.sh b/benches/javascript/setup.sh new file mode 100755 index 0000000..15cb80f --- /dev/null +++ b/benches/javascript/setup.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e + +cd ../../wasm && ./build.sh nodejs +cd ../benches/javascript && npm link jsonpath-wasm \ No newline at end of file diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml index 7c2a7d8..5aa129d 100644 --- a/wasm/Cargo.toml +++ b/wasm/Cargo.toml @@ -14,7 +14,7 @@ license = "MIT" crate-type = ["cdylib", "rlib"] [features] -default = ["console_error_panic_hook"] +default = ["console_error_panic_hook", "wee_alloc"] [dependencies] cfg-if = "0.1.2" diff --git a/wasm/node_modules/jsonpath-wasm b/wasm/node_modules/jsonpath-wasm new file mode 120000 index 0000000..d9b23dc --- /dev/null +++ b/wasm/node_modules/jsonpath-wasm @@ -0,0 +1 @@ +../../../../../.nvm/versions/node/v11.10.1/lib/node_modules/jsonpath-wasm \ No newline at end of file diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs index 1e0e4f6..ce2a0ca 100644 --- a/wasm/src/lib.rs +++ b/wasm/src/lib.rs @@ -92,4 +92,8 @@ pub fn read(js_value: JsValue, path: &str) -> JsValue { Ok(node) => into_js_value(&js_value, node), Err(e) => return JsValue::from_str(e.as_str()) } +} + +#[wasm_bindgen] +pub fn testa() { } \ No newline at end of file