Skip to content

Commit

Permalink
perf: writeToBuffer (#4)
Browse files Browse the repository at this point in the history
Co-authored-by: xieweicheng <xieweicheng@bytedance.com>
  • Loading branch information
Tseian and xieweicheng committed Jun 28, 2022
1 parent a51c6f8 commit 6bfcbe2
Show file tree
Hide file tree
Showing 19 changed files with 339 additions and 100 deletions.
4 changes: 4 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
"max-len": [
"error",
{ "code": 80 }
],
"quotes": [
"error",
"single"
]
},
"overrides": [
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ node_modules
# Vim
*.swp

package-lock.json
17 changes: 17 additions & 0 deletions benchmarks/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "benchmarks",
"version": "1.0.0",
"description": "",
"main": "writeToBuffer.js",
"scripts": {
"bench-1": "node writeToBuffer.js",
"bench-2":"VERSION=2.0.2 node writeToBuffer.js",
"bench":"npm run bench-1 && npm run bench-2"
},
"author": "",
"license": "ISC",
"dependencies": {
"mcnbt": "2.0.1",
"benchmark": "^2.1.4"
}
}
124 changes: 124 additions & 0 deletions benchmarks/writeToBuffer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
'use strict';

/**
v: 2.0.1 , r: 1b x 66,319 ops/sec ±70.40% (88 runs sampled)
v: 2.0.1 , r: 1kb x 32,589 ops/sec ±0.96% (90 runs sampled)
v: 2.0.1 , r: 2kb x 18,932 ops/sec ±0.51% (93 runs sampled)
v: 2.0.1 , r: 4kb x 10,554 ops/sec ±0.44% (94 runs sampled)
v: 2.0.1 , r: 8kb x 5,425 ops/sec ±0.56% (91 runs sampled)
v: 2.0.2 , r: 1b x 159,682 ops/sec ±0.49% (92 runs sampled)
v: 2.0.2 , r: 1kb x 35,753 ops/sec ±0.57% (90 runs sampled)
v: 2.0.2 , r: 2kb x 19,579 ops/sec ±0.67% (95 runs sampled)
v: 2.0.2 , r: 4kb x 10,397 ops/sec ±0.48% (95 runs sampled)
v: 2.0.2 , r: 8kb x 5,168 ops/sec ±0.35% (95 runs sampled)
*/

let NBT;
let version;

if (process.env.VERSION === '2.0.2') {
NBT = require('../');
version = '2.0.2';
} else {
NBT = require('mcnbt');
version = '2.0.1';
}

const Benchmark = require('benchmark');

function test(byteCount = 5) {
const short = new NBT.Tags.TAGShort();
short.setValue(100);
short.id = 'short';

const long = new NBT.Tags.TAGLong();
long.setValue(1000);
long.id = 'long';

const float = new NBT.Tags.TAGFloat();
float.setValue(1.0);
float.id = 'float';

const double = new NBT.Tags.TAGDouble();
double.setValue(1.0);
double.id = 'double';

const byte = new NBT.Tags.TAGByte();
byte.setValue(1);
byte.id = 'byte';

const string = new NBT.Tags.TAGString();
let str = 'str';
for (let i = 0; i < byteCount; i++) {
str += 's';
}
string.setValue(str);
string.id = 'string';

const intArray = new NBT.Tags.TAGIntArray();
intArray.setValue(new Array(byteCount).fill(0));
intArray.id = 'intArray';

const int = new NBT.Tags.TAGInt();
int.setValue(1);
int.id = 'int';

const list = new NBT.Tags.TAGList();
list.id = 'list';

const l = [ short, short ];
list.setValue(l);

const resultNBT = new NBT.Tags.TAGCompound();
resultNBT.id = 'result';
resultNBT.setValue({
short,
long,
float,
double,
byte,
string,
intArray,
int,
list,
});

const nbt = new NBT();
nbt.root.result = resultNBT;

return nbt.writeToBuffer().length;
}
console.log('1b:byteLength:', test(), 'b');
console.log('1kb:byteLength:', test(1024), 'b');
console.log('2kb:byteLength:', test(2048), 'b');
console.log('4kb:byteLength:', test(4096), 'b');
console.log('8kb:byteLength:', test(8192), 'b');

const suite = new Benchmark.Suite('', {});

suite
.add('1b', () => {
test(1);
})
.add('1kb', () => {
test(1024);
})
.add('2kb', () => {
test(2048);
})
.add('4kb', () => {
test(4096);
})
.add('8kb', () => {
test(8192);
});

suite
.on('cycle', event => {
console.log('v:', version, ', r:', String(event.target));
})
.on('complete', () => {
//
})
.run();
104 changes: 104 additions & 0 deletions lib/bvffer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
'use strict';

const defaultPoolSize = 64 * 1024;
if (Buffer.poolSize < defaultPoolSize) {
Buffer.poolSize = defaultPoolSize;
}

class Bvffer {
constructor(buffByteLength) {
/**
* Buffer store data
*/
this.buffer = Buffer.allocUnsafe(buffByteLength);
/**
* data length in buffer
*/
this.dataByteLength = 0;
}

get dataLength() {
return this.dataByteLength;
}

get buff() {
return this.buffer;
}

/**
* write buffer data to buffer
* @param {Buffer} value data to write
*/
writeBuffer(value) {
this.writeUInt16BE(value.length);

value.copy(this.buffer, this.dataByteLength);
this.dataByteLength += value.length;
}

/**
* @param {number} value value
*/
writeUInt8(value) {
this.buff[this.dataByteLength] = value;
this.dataByteLength += 1;
}

/**
* @param {number} value value
*/
writeInt8(value) {
this.buff[this.dataByteLength] = value;
this.dataByteLength += 1;
}

/**
* @param {number} value value
*/
writeUInt16BE(value) {
this.buffer.writeUInt16BE(value, this.dataByteLength);
this.dataByteLength += 2;
}

/**
* @param {number} value value
*/
writeInt16BE(value) {
this.buffer.writeInt16BE(value, this.dataByteLength);
this.dataByteLength += 2;
}

/**
* @param {number} value value
*/
writeUInt32BE(value) {
this.buffer.writeUInt32BE(value, this.dataByteLength);
this.dataByteLength += 4;
}

/**
* @param {number} value value
*/
writeInt32BE(value) {
this.buffer.writeInt32BE(value, this.dataByteLength);
this.dataByteLength += 4;
}

/**
* @param {number} value value
*/
writeDoubleBE(value) {
this.buffer.writeDoubleBE(value, this.dataByteLength);
this.dataByteLength += 8;
}

/**
* @param {number} value value
*/
writeFloatBE(value) {
this.buffer.writeFloatBE(value, this.dataByteLength);
this.dataByteLength += 4;
}
}

exports.Bvffer = Bvffer;
6 changes: 2 additions & 4 deletions lib/tags/byte.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,9 @@ class TAGByte extends BaseTag {
* Write body to buffer
* @param {Buffer} buff The buffer to write to
* @param {number} offset The offset to start writing to
* @return {number} The number of bytes written
*/
writeBuffer(buff, offset) {
buff.writeInt8(this.value, offset);
return 1;
writeBuffer(buff) {
buff.writeInt8(this.value);
}

/**
Expand Down
12 changes: 5 additions & 7 deletions lib/tags/byte_array.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class TAGByteArray extends BaseTag {
constructor() {
super();
this.type = 'TAG_Byte_Array';
this.value = [];
}

/**
Expand Down Expand Up @@ -43,18 +44,15 @@ class TAGByteArray extends BaseTag {

/**
* Write body to buffer
* @param {Buffer} buff The buffer to write to
* @param {Bvffer} buff The buffer to write to
* @param {number} offset The offset to start writing from
* @return {number} The number of bytes written
*/
writeBuffer(buff, offset) {
buff.writeUInt32BE(this.value.length, offset);
writeBuffer(buff) {
buff.writeUInt32BE(this.value.length);

for (let i = 0; i < this.value.length; i++) {
buff.writeInt8(this.value[i], offset + 4 + i);
buff.writeInt8(this.value[i]);
}

return 4 + this.value.length;
}

/**
Expand Down
23 changes: 8 additions & 15 deletions lib/tags/compound.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ class TAGCompound extends BaseTag {

// child type id for 1 byte, child name length for 2 bytes and child
// name for (child name length) byte(s).
len += 1;
len += 2;
len += 3;
len += Buffer.byteLength(this.value[key].id, 'utf8');

// add the child body's length
Expand All @@ -101,29 +100,23 @@ class TAGCompound extends BaseTag {

/**
* Write body to buffer
* @param {Buffer} buff The buffer to write to
* @param {Bvffer} buff The buffer to write to
* @param {number} offset The offset to start writing to
* @return {number} The number of bytes written
*/
writeBuffer(buff, offset) {
let len = 0;
writeBuffer(buff) {
for (const key in this.value) {
if (!this.value.hasOwnProperty(key)) continue;

const object = this.value[key];
buff.writeUInt8(object.getTypeId(), offset + len);
buff.writeUInt8(object.getTypeId());

const nameBuff = new Buffer(object.id, 'utf8');
nameBuff.copy(buff, offset + len + 1 + 2);
buff.writeUInt16BE(nameBuff.length, offset + len + 1);
const nameBuff = Buffer.from(object.id, 'utf8');
buff.writeBuffer(nameBuff);

len += object.writeBuffer(buff, offset + len + 1 + 2 + nameBuff.length);
len += (1 + 2 + nameBuff.length);
object.writeBuffer(buff);
}

buff.writeUInt8(0, offset + len);
len += 1;
return len;
buff.writeUInt8(0);
}

/**
Expand Down
7 changes: 2 additions & 5 deletions lib/tags/double.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,9 @@ class TAGDouble extends BaseTag {
/**
* Write body to buffer
* @param {Buffer} buff The buffer to write to
* @param {number} offset The offset to start writing to
* @return {number} The number of bytes written
*/
writeBuffer(buff, offset) {
buff.writeDoubleBE(this.value, offset);
return 8;
writeBuffer(buff) {
buff.writeDoubleBE(this.value);
}

/**
Expand Down
7 changes: 2 additions & 5 deletions lib/tags/float.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,9 @@ class TAGFloat extends BaseTag {
/**
* Write body to buffer
* @param {Buffer} buff The buffer to write to
* @param {number} offset The offset to start writing to
* @return {number} The number of bytes written
*/
writeBuffer(buff, offset) {
buff.writeFloatBE(this.value, offset);
return 4;
writeBuffer(buff) {
buff.writeFloatBE(this.value);
}

/**
Expand Down

0 comments on commit 6bfcbe2

Please sign in to comment.