Skip to content

Commit

Permalink
Replace Buffer with Uint8Array (#452)
Browse files Browse the repository at this point in the history
This change updates binary encoding to use `Uint8Array`s
instead of `Buffer` instances. It increases portability of
the library while also improving performance.
  • Loading branch information
valadaptive committed Sep 21, 2024
1 parent 244a90c commit c80c670
Show file tree
Hide file tree
Showing 21 changed files with 707 additions and 520 deletions.
2 changes: 1 addition & 1 deletion doc
Submodule doc updated from bebd04 to b36b2f
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
'use strict';

let io = require('node-avro-io'),
avsc = require('../../../../lib');
avsc = require('../../../../lib'),
{isBufferLike} = require('../../../../lib/utils');


let loops = 2;
Expand All @@ -30,7 +31,7 @@ avsc.createFileDecoder(process.argv[2])
});

function deserialize(buffer) {
if (!Buffer.isBuffer(buffer)) {
if (!isBufferLike(buffer)) {
throw 'Buffer object expected';
}

Expand All @@ -44,7 +45,7 @@ function deserialize(buffer) {
this._i += len;
return len == 1 ?
buffer[i] :
buffer.slice(i, this._i);
buffer.subarray(i, this._i);
},
skip: function(len) {
if (this._i + len > buffer.length) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
'use strict';

let io = require('node-avro-io'),
avsc = require('../../../../lib');
avsc = require('../../../../lib'),
{isBufferLike} = require('../../../../lib/utils');


let loops = 2;
Expand Down Expand Up @@ -33,7 +34,7 @@ function serialize(datum) {
let buffer = Buffer.from([]);
let encoder = new io.IO.BinaryEncoder({
write: function(data) {
if (!Buffer.isBuffer(data)) {
if (!isBufferLike(data)) {
data = Buffer.from([data]);
}
buffer = Buffer.concat([buffer, data]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
'use strict';

let avro = require('etp-avro'),
{Buffer} = require('buffer'),
avsc = require('../../../../lib');


Expand Down Expand Up @@ -31,8 +32,8 @@ avsc.createFileDecoder(process.argv[2])
function loop() {
let n = 0;
for (let i = 0, l = records.length; i < l; i++) {
// We need to slice to force a copy otherwise the array is shared.
let buf = writer.encode(schema, records[i]).slice();
// We need to force a copy otherwise the array is shared.
let buf = Buffer.from(writer.encode(schema, records[i]));
n += buf[0] + buf.length;
}
return n;
Expand Down
3 changes: 2 additions & 1 deletion etc/benchmarks/js-serialization-libraries/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

let avro = require('../../../lib'),
{isBufferLike} = require('../../../../lib/utils'),
Benchmark = require('benchmark'),
commander = require('commander'),
compactr = require('compactr'),
Expand Down Expand Up @@ -285,7 +286,7 @@ class EncodeSuite extends Suite {
let val = this.getValue();
return function () {
let str = JSON.stringify(val, (key, value) => {
if (Buffer.isBuffer(value)) {
if (isBufferLike(value)) {
return value.toString('binary');
}
return value;
Expand Down
4 changes: 1 addition & 3 deletions etc/browser/avsc.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@
*/

let containers = require('../../lib/containers'),
utils = require('../../lib/utils'),
stream = require('stream');


/** Transform stream which lazily reads a blob's contents. */
class BlobReader extends stream.Readable {
constructor (blob, opts) {
Expand Down Expand Up @@ -39,7 +37,7 @@ class BlobReader extends stream.Readable {
if (evt.error) {
self.emit('error', evt.error);
} else {
self.push(utils.bufferFrom(reader.result));
self.push(reader.result);
}
}, false);
reader.readAsArrayBuffer(blob);
Expand Down
8 changes: 3 additions & 5 deletions etc/browser/lib/md5.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@
*
*/

let buffer = require('buffer');
let Buffer = buffer.Buffer;

function md5cycle(x, k) {
let a = x[0], b = x[1], c = x[2], d = x[3];

Expand Down Expand Up @@ -148,9 +145,10 @@ function md5blk(s) {

function md5(s) {
let arr = md51(s);
let buf = Buffer.alloc(16);
let buf = new Uint8Array(16);
let dv = new DataView(buf.buffer);
for (let i = 0; i < 4; i++) {
buf.writeIntLE(arr[i], i * 4, 4);
dv.setInt32(i * 4, arr[i], true);
}
return buf;
}
Expand Down
10 changes: 10 additions & 0 deletions etc/schemas/Float.avsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "Float",
"type": "record",
"fields": [
{
"name": "value",
"type": "float"
}
]
}
4 changes: 3 additions & 1 deletion etc/scripts/infer
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ switch (argv.length) {
process.exit(1);
}

const DECODER = new TextDecoder();

/**
* Infer a type from a stream of serialized JSON values.
*
Expand All @@ -42,7 +44,7 @@ function fromStdin() {
let str = '';
process.stdin
.on('data', (buf) => {
str += buf.toString();
str += DECODER.decode(buf);
let pos;
while ((pos = utils.jsonEnd(str)) >= 0) {
let val = JSON.parse(str.slice(0, pos));
Expand Down
3 changes: 2 additions & 1 deletion etc/scripts/meta
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ META_TYPE.fromBuffer = function (buf) {
return avro.Type.forType(attrs, {wrapUnions: true});
};

const DECODER = new TextDecoder();

// Example of things we can do.
switch (process.argv[2]) {
Expand All @@ -141,7 +142,7 @@ switch (process.argv[2]) {
if (err) {
throw err;
}
let type = avro.Type.forSchema(buf.toString());
let type = avro.Type.forSchema(DECODER.decode(buf));
process.stdout.write(META_TYPE.toBuffer(type));
});
break;
Expand Down
11 changes: 11 additions & 0 deletions etc/scripts/perf
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ if (~index) {
// serialization speed).
let NUM_VALUES = 1000;

function maybeGC() {
try {
global.gc();
} catch (err) {
// GC not exposed
}
}

// Header formatting is done according to GitHub flavored Markdown.
console.log(['fromBuffer', 'toBuffer', 'isValid ', '(ops/sec)'].join('\t| '));
console.log(['---------:', '-------:', '------: ', '---------'].join('\t| '));
Expand All @@ -58,6 +66,7 @@ paths.forEach((fpath) => {
stats.push(s);
});

maybeGC();
bench.clone({fn: function () {
for (let i = 0, l = NUM_VALUES; i < l; i++) {
let val = type.fromBuffer(bufs[i]);
Expand All @@ -67,6 +76,7 @@ paths.forEach((fpath) => {
}
}}).run();

maybeGC();
bench.clone({fn: function () {
for (let i = 0, l = NUM_VALUES; i < l; i++) {
let buf = type.toBuffer(values[i]);
Expand All @@ -76,6 +86,7 @@ paths.forEach((fpath) => {
}
}}).run();

maybeGC();
bench.clone({fn: function () {
for (let i = 0, l = NUM_VALUES; i < l; i++) {
if (!type.isValid(values[i])) {
Expand Down
Loading

0 comments on commit c80c670

Please sign in to comment.