From fc9014822d9cdeae8c6e454ccb66ee28f579826c Mon Sep 17 00:00:00 2001 From: dcodeIO Date: Tue, 6 Dec 2016 23:18:30 +0100 Subject: [PATCH] Automatic profile generation and processing [ci skip] --- README.md | 16 ++++++++++++++++ bench/prof.js | 44 ++++++++++++++++++++++++++++++++++++++------ package.json | 4 +--- src/writer.js | 2 +- tests/empty.js | 17 +++++++++++++++++ 5 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 tests/empty.js diff --git a/README.md b/README.md index c4bc3c7fa..5a48a47ab 100644 --- a/README.md +++ b/README.md @@ -282,6 +282,22 @@ Documentation * [protobuf.js API Documentation](http://dcode.io/protobuf.js/) +### Data type recommendations + +| Value type | protobuf Type | Size / Notes +|--------------------------|---------------|----------------------------------------------------------------------------------- +| Unsigned 32 bit integers | uint32 | 1 to 5 bytes. +| Signed 32 bit integers | sint32 | 1 to 5 bytes. Do not use int32 (always encodes negative values as 10 bytes). +| Unsigned 52 bit integers | uint64 | 1 to 10 bytes. +| Signed 52 bit integers | sint64 | 1 to 10 bytes. Do not use int64 (always encodes negative values as 10 bytes). +| Unsigned 64 bit integers | uint64 | Use with long.js. 1 to 10 bytes. +| Signed 64 bit integers | sint64 | Use with long.js. 1 to 10 bytes. Do not use int64 (always encodes negative values as 10 bytes). +| 32 bit precision floats | float | 4 bytes. +| 64 bit precision floats | double | 8 bytes. Use float if 32 bits of precision are enough. +| Boolean values | bool | 1 byte. +| Strings | string | 1 byte + utf8 byte length. +| Buffers | bytes | 1 byte + byte length. + Command line ------------ diff --git a/bench/prof.js b/bench/prof.js index 1cb4992f2..12313db05 100644 --- a/bench/prof.js +++ b/bench/prof.js @@ -1,8 +1,44 @@ var fs = require("fs"), path = require("path"); -var protobuf = require(".."); -// A profiling stub to measure just raw encoding / decoding performance using benchmark data. +// A profiling stub to measure encoding / decoding performance using benchmark data. + +var commands = ["encode", "decode", "encode-browser", "decode-browser"]; +if (commands.indexOf(process.argv[2]) < 0) { // 0: node, 1: prof.js + console.error("usage: " + path.basename(process.argv[1]) + " <" + commands.join('|') + "> [iterations=10000000]"); + process.exit(0); +} + +// Spin up a node process with profiling enabled and process the generated log +if (process.execArgv.indexOf("--prof") < 0) { + console.log("cleaning up old logs ..."); + var child_process = require("child_process"); + var logRe = /^isolate\-[0-9A-F]+\-v8\.log$/; + fs.readdirSync(process.cwd()).forEach(function(file) { + if (logRe.test(file)) + fs.unlink(file); + }); + console.log("generating profile (may take a while) ..."); + child_process.execSync("node --prof --trace-deopt " + process.argv.slice(1).join(' '), { + cwd: process.cwd(), + stdio: 'inherit' + }); + console.log("processing profile ..."); + fs.readdirSync(process.cwd()).forEach(function(file) { + if (logRe.test(file)) { + child_process.execSync("node --prof-process " + file, { + cwd: process.cwd(), + stdio: 'inherit' + }); + fs.unlink(file); + } + }); + console.log("done."); + process.exit(0); +} + +// Actual profiling code +var protobuf = require(".."); var root = protobuf.parse(fs.readFileSync(require.resolve("../bench/bench.proto")).toString("utf8")).root; var Test = root.lookup("Test"); @@ -16,10 +52,6 @@ function setupBrowser() { } switch (process.argv[2]) { - default: - console.error("usage: " + path.basename(process.argv[1]) + " [iterations=10000000]"); - process.exit(1); - return; case "encode-browser": setupBrowser(); case "encode": diff --git a/package.json b/package.json index 767c4f088..75e486220 100644 --- a/package.json +++ b/package.json @@ -33,9 +33,7 @@ "zuul": "zuul --ui tape --no-coverage --concurrency 4 -- tests/*.js", "zuul-local": "zuul --ui tape --no-coverage --concurrency 1 --local 8080 --disable-tunnel -- tests/*.js", "bench": "node bench", - "bench-read": "node bench/read", - "bench-write": "node bench/write", - "all": "npm run lint && npm run test && npm run build && npm run types && npm run docs && npm run bench", + "prof": "node bench/prof", "prepublish": "node scripts/prepublish" }, "optionalDependencies": { diff --git a/src/writer.js b/src/writer.js index 33551d44a..11530b287 100644 --- a/src/writer.js +++ b/src/writer.js @@ -563,7 +563,7 @@ function BufferWriter() { BufferWriter.alloc = function alloc_buffer(size) { BufferWriter.alloc = util.Buffer.allocUnsafe ? util.Buffer.allocUnsafe - : function allocUnsafe(size) { return new util.Buffer(size); }; + : function allocUnsafeNew(size) { return new util.Buffer(size); }; return BufferWriter.alloc(size); }; diff --git a/tests/empty.js b/tests/empty.js new file mode 100644 index 000000000..9f97a66d7 --- /dev/null +++ b/tests/empty.js @@ -0,0 +1,17 @@ +var tape = require("tape"); + +var protobuf = require(".."); + +tape.test("empty messages", function(test) { + var root = new protobuf.Root().addJSON({ + "Test": { + fields: {} + } + }); + + var Test = root.lookup("Test"); + var buf = Test.encodeDelimited({}).finish(); + test.equal(buf.length, 1, "should encodeDelimited to a buffer of length 1"); + test.equal(buf[0], 0, "should encodeDelimited a length of 0"); + test.end(); +});