| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 63d361b commit 4014ecb
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,61 +1,90 @@ | |||
| 1 | 1 | 'use strict'; | |
| 2 | 2 | ||
| 3 | 3 | const common = require('../common.js'); | |
| 4 | + const v8 = require('v8'); | ||
| 4 | 5 | ||
| 5 | 6 | const bench = common.createBenchmark(main, { | |
| 6 | - method: ['swap16', 'swap32', 'htons', 'htonl'], | ||
| 7 | - len: [4, 64, 512, 768, 1024, 1536, 2056, 4096, 8192], | ||
| 8 | - n: [1e6] | ||
| 7 | + aligned: ['true', 'false'], | ||
| 8 | + method: ['swap16', 'swap32', 'swap64'/*, 'htons', 'htonl', 'htonll'*/], | ||
| 9 | + len: [8, 64, 128, 256, 512, 768, 1024, 1536, 2056, 4096, 8192], | ||
| 10 | + n: [5e7] | ||
| 9 | 11 | }); | |
| 10 | 12 | ||
| 11 | 13 | // The htons and htonl methods below are used to benchmark the | |
| 12 | 14 | // performance difference between doing the byteswap in pure | |
| 13 | 15 | // javascript regardless of Buffer size as opposed to dropping | |
| 14 | - // down to the native layer for larger Buffer sizes. | ||
| 16 | + // down to the native layer for larger Buffer sizes. Commented | ||
| 17 | + // out by default because they are slow for big buffers. If | ||
| 18 | + // re-evaluating the crossover point, uncomment those methods | ||
| 19 | + // and comment out their implementations in lib/buffer.js so | ||
| 20 | + // C++ version will always be used. | ||
| 21 | + | ||
| 22 | + function swap(b, n, m) { | ||
| 23 | + const i = b[n]; | ||
| 24 | + b[n] = b[m]; | ||
| 25 | + b[m] = i; | ||
| 26 | + } | ||
| 15 | 27 | ||
| 16 | 28 | Buffer.prototype.htons = function htons() { | |
| 17 | 29 | if (this.length % 2 !== 0) | |
| 18 | 30 | throw new RangeError(); | |
| 19 | - for (var i = 0, n = 0; i < this.length; i += 2) { | ||
| 20 | - n = this[i]; | ||
| 21 | - this[i] = this[i + 1]; | ||
| 22 | - this[i + 1] = n; | ||
| 31 | + for (var i = 0; i < this.length; i += 2) { | ||
| 32 | + swap(this, i, i + 1); | ||
| 23 | 33 | } | |
| 24 | 34 | return this; | |
| 25 | 35 | }; | |
| 26 | 36 | ||
| 27 | 37 | Buffer.prototype.htonl = function htonl() { | |
| 28 | - if (this.length % 2 !== 0) | ||
| 38 | + if (this.length % 4 !== 0) | ||
| 39 | + throw new RangeError(); | ||
| 40 | + for (var i = 0; i < this.length; i += 4) { | ||
| 41 | + swap(this, i, i + 3); | ||
| 42 | + swap(this, i + 1, i + 2); | ||
| 43 | + } | ||
| 44 | + return this; | ||
| 45 | + }; | ||
| 46 | + | ||
| 47 | + Buffer.prototype.htonll = function htonl() { | ||
| 48 | + if (this.length % 8 !== 0) | ||
| 29 | 49 | throw new RangeError(); | |
| 30 | - for (var i = 0, n = 0; i < this.length; i += 4) { | ||
| 31 | - n = this[i]; | ||
| 32 | - this[i] = this[i + 3]; | ||
| 33 | - this[i + 3] = n; | ||
| 34 | - n = this[i + 1]; | ||
| 35 | - this[i + 1] = this[i + 2]; | ||
| 36 | - this[i + 2] = n; | ||
| 50 | + for (var i = 0; i < this.length; i += 8) { | ||
| 51 | + swap(this, i, i + 7); | ||
| 52 | + swap(this, i + 1, i + 6); | ||
| 53 | + swap(this, i + 2, i + 5); | ||
| 54 | + swap(this, i + 3, i + 4); | ||
| 37 | 55 | } | |
| 38 | 56 | return this; | |
| 39 | 57 | }; | |
| 40 | 58 | ||
| 41 | - function createBuffer(len) { | ||
| 59 | + function createBuffer(len, aligned) { | ||
| 60 | + len += aligned ? 0 : 1; | ||
| 42 | 61 | const buf = Buffer.allocUnsafe(len); | |
| 43 | 62 | for (var i = 1; i <= len; i++) | |
| 44 | 63 | buf[i - 1] = i; | |
| 45 | - return buf; | ||
| 64 | + return aligned ? buf : buf.slice(1); | ||
| 46 | 65 | } | |
| 47 | 66 | ||
| 48 | - function bufferSwap(n, buf, method) { | ||
| 49 | - for (var i = 1; i <= n; i++) | ||
| 50 | - buf[method](); | ||
| 67 | + function genMethod(method) { | ||
| 68 | + const fnString = | ||
| 69 | + 'return function ' + method + '(n, buf) {' + | ||
| 70 | + ' for (var i = 0; i <= n; i++)' + | ||
| 71 | + ' buf.' + method + '();' + | ||
| 72 | + '}'; | ||
| 73 | + return (new Function(fnString))(); | ||
| 51 | 74 | } | |
| 52 | 75 | ||
| 53 | 76 | function main(conf) { | |
| 54 | 77 | const method = conf.method; | |
| 55 | 78 | const len = conf.len | 0; | |
| 56 | 79 | const n = conf.n | 0; | |
| 57 | - const buf = createBuffer(len); | ||
| 80 | + const aligned = conf.aligned || 'true'; | ||
| 81 | + const buf = createBuffer(len, aligned === 'true'); | ||
| 82 | + const bufferSwap = genMethod(method); | ||
| 83 | + | ||
| 84 | + v8.setFlagsFromString('--allow_natives_syntax'); | ||
| 85 | + eval('%OptimizeFunctionOnNextCall(bufferSwap)'); | ||
| 86 | + | ||
| 58 | 87 | bench.start(); | |
| 59 | - bufferSwap(n, buf, method); | ||
| 88 | + bufferSwap(n, buf); | ||
| 60 | 89 | bench.end(n); | |
| 61 | 90 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1461,10 +1461,10 @@ calls can be chained. | |||
| 1461 | 1461 | ```js | |
| 1462 | 1462 | const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); | |
| 1463 | 1463 | console.log(buf); | |
| 1464 | - // Prints Buffer(0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8) | ||
| 1464 | + // Prints <Buffer 01 02 03 04 05 06 07 08> | ||
| 1465 | 1465 | buf.swap16(); | |
| 1466 | 1466 | console.log(buf); | |
| 1467 | - // Prints Buffer(0x2, 0x1, 0x4, 0x3, 0x6, 0x5, 0x8, 0x7) | ||
| 1467 | + // Prints <Buffer 02 01 04 03 06 05 08 07> | ||
| 1468 | 1468 | ``` | |
| 1469 | 1469 | ||
| 1470 | 1470 | ### buf.swap32() | |
@@ -1482,12 +1482,36 @@ calls can be chained. | |||
| 1482 | 1482 | ```js | |
| 1483 | 1483 | const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); | |
| 1484 | 1484 | console.log(buf); | |
| 1485 | - // Prints Buffer(0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8) | ||
| 1485 | + // Prints <Buffer 01 02 03 04 05 06 07 08> | ||
| 1486 | 1486 | buf.swap32(); | |
| 1487 | 1487 | console.log(buf); | |
| 1488 | - // Prints Buffer(0x4, 0x3, 0x2, 0x1, 0x8, 0x7, 0x6, 0x5) | ||
| 1488 | + // Prints <Buffer 04 03 02 01 08 07 06 05> | ||
| 1489 | 1489 | ``` | |
| 1490 | 1490 | ||
| 1491 | + ### buf.swap64() | ||
| 1492 | + <!-- YAML | ||
| 1493 | + added: REPLACEME | ||
| 1494 | + --> | ||
| 1495 | + | ||
| 1496 | + * Return: {Buffer} | ||
| 1497 | + | ||
| 1498 | + Interprets the `Buffer` as an array of 64-bit numbers and swaps | ||
| 1499 | + the byte-order *in-place*. Throws a `RangeError` if the `Buffer` length is | ||
| 1500 | + not a multiple of 64 bits. The method returns a reference to the Buffer, so | ||
| 1501 | + calls can be chained. | ||
| 1502 | + | ||
| 1503 | + ```js | ||
| 1504 | + const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); | ||
| 1505 | + console.log(buf); | ||
| 1506 | + // Prints <Buffer 01 02 03 04 05 06 07 08> | ||
| 1507 | + buf.swap64(); | ||
| 1508 | + console.log(buf); | ||
| 1509 | + // Prints <Buffer 08 07 06 05 04 03 02 01> | ||
| 1510 | + ``` | ||
| 1511 | + | ||
| 1512 | + Note that JavaScript cannot encode 64-bit integers. This method is intended | ||
| 1513 | + for working with 64-bit floats. | ||
| 1514 | + | ||
| 1491 | 1515 | ### buf.toString([encoding[, start[, end]]]) | |
| 1492 | 1516 | ||
| 1493 | 1517 | * `encoding` {String} Default: `'utf8'` | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -24,47 +24,6 @@ var poolSize, poolOffset, allocPool; | |||
| 24 | 24 | ||
| 25 | 25 | binding.setupBufferJS(Buffer.prototype, bindingObj); | |
| 26 | 26 | ||
| 27 | - const swap16n = binding.swap16; | ||
| 28 | - const swap32n = binding.swap32; | ||
| 29 | - | ||
| 30 | - function swap(b, n, m) { | ||
| 31 | - const i = b[n]; | ||
| 32 | - b[n] = b[m]; | ||
| 33 | - b[m] = i; | ||
| 34 | - } | ||
| 35 | - | ||
| 36 | - Buffer.prototype.swap16 = function swap16() { | ||
| 37 | - // For Buffer.length < 512, it's generally faster to | ||
| 38 | - // do the swap in javascript. For larger buffers, | ||
| 39 | - // dropping down to the native code is faster. | ||
| 40 | - const len = this.length; | ||
| 41 | - if (len % 2 !== 0) | ||
| 42 | - throw new RangeError('Buffer size must be a multiple of 16-bits'); | ||
| 43 | - if (len < 512) { | ||
| 44 | - for (var i = 0; i < len; i += 2) | ||
| 45 | - swap(this, i, i + 1); | ||
| 46 | - return this; | ||
| 47 | - } | ||
| 48 | - return swap16n.apply(this); | ||
| 49 | - }; | ||
| 50 | - | ||
| 51 | - Buffer.prototype.swap32 = function swap32() { | ||
| 52 | - // For Buffer.length < 1024, it's generally faster to | ||
| 53 | - // do the swap in javascript. For larger buffers, | ||
| 54 | - // dropping down to the native code is faster. | ||
| 55 | - const len = this.length; | ||
| 56 | - if (len % 4 !== 0) | ||
| 57 | - throw new RangeError('Buffer size must be a multiple of 32-bits'); | ||
| 58 | - if (len < 1024) { | ||
| 59 | - for (var i = 0; i < len; i += 4) { | ||
| 60 | - swap(this, i, i + 3); | ||
| 61 | - swap(this, i + 1, i + 2); | ||
| 62 | - } | ||
| 63 | - return this; | ||
| 64 | - } | ||
| 65 | - return swap32n.apply(this); | ||
| 66 | - }; | ||
| 67 | - | ||
| 68 | 27 | const flags = bindingObj.flags; | |
| 69 | 28 | const kNoZeroFill = 0; | |
| 70 | 29 | ||
@@ -1320,3 +1279,67 @@ Buffer.prototype.writeDoubleBE = function writeDoubleBE(val, offset, noAssert) { | |||
| 1320 | 1279 | binding.writeDoubleBE(this, val, offset, true); | |
| 1321 | 1280 | return offset + 8; | |
| 1322 | 1281 | }; | |
| 1282 | + | ||
| 1283 | + const swap16n = binding.swap16; | ||
| 1284 | + const swap32n = binding.swap32; | ||
| 1285 | + const swap64n = binding.swap64; | ||
| 1286 | + | ||
| 1287 | + function swap(b, n, m) { | ||
| 1288 | + const i = b[n]; | ||
| 1289 | + b[n] = b[m]; | ||
| 1290 | + b[m] = i; | ||
| 1291 | + } | ||
| 1292 | + | ||
| 1293 | + | ||
| 1294 | + Buffer.prototype.swap16 = function swap16() { | ||
| 1295 | + // For Buffer.length < 128, it's generally faster to | ||
| 1296 | + // do the swap in javascript. For larger buffers, | ||
| 1297 | + // dropping down to the native code is faster. | ||
| 1298 | + const len = this.length; | ||
| 1299 | + if (len % 2 !== 0) | ||
| 1300 | + throw new RangeError('Buffer size must be a multiple of 16-bits'); | ||
| 1301 | + if (len < 128) { | ||
| 1302 | + for (var i = 0; i < len; i += 2) | ||
| 1303 | + swap(this, i, i + 1); | ||
| 1304 | + return this; | ||
| 1305 | + } | ||
| 1306 | + return swap16n(this); | ||
| 1307 | + }; | ||
| 1308 | + | ||
| 1309 | + | ||
| 1310 | + Buffer.prototype.swap32 = function swap32() { | ||
| 1311 | + // For Buffer.length < 192, it's generally faster to | ||
| 1312 | + // do the swap in javascript. For larger buffers, | ||
| 1313 | + // dropping down to the native code is faster. | ||
| 1314 | + const len = this.length; | ||
| 1315 | + if (len % 4 !== 0) | ||
| 1316 | + throw new RangeError('Buffer size must be a multiple of 32-bits'); | ||
| 1317 | + if (len < 192) { | ||
| 1318 | + for (var i = 0; i < len; i += 4) { | ||
| 1319 | + swap(this, i, i + 3); | ||
| 1320 | + swap(this, i + 1, i + 2); | ||
| 1321 | + } | ||
| 1322 | + return this; | ||
| 1323 | + } | ||
| 1324 | + return swap32n(this); | ||
| 1325 | + }; | ||
| 1326 | + | ||
| 1327 | + | ||
| 1328 | + Buffer.prototype.swap64 = function swap64() { | ||
| 1329 | + // For Buffer.length < 192, it's generally faster to | ||
| 1330 | + // do the swap in javascript. For larger buffers, | ||
| 1331 | + // dropping down to the native code is faster. | ||
| 1332 | + const len = this.length; | ||
| 1333 | + if (len % 8 !== 0) | ||
| 1334 | + throw new RangeError('Buffer size must be a multiple of 64-bits'); | ||
| 1335 | + if (len < 192) { | ||
| 1336 | + for (var i = 0; i < len; i += 8) { | ||
| 1337 | + swap(this, i, i + 7); | ||
| 1338 | + swap(this, i + 1, i + 6); | ||
| 1339 | + swap(this, i + 2, i + 5); | ||
| 1340 | + swap(this, i + 3, i + 4); | ||
| 1341 | + } | ||
| 1342 | + return this; | ||
| 1343 | + } | ||
| 1344 | + return swap64n(this); | ||
| 1345 | + }; | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments