From 69166b9c0e0ee5751d50ae424cdfc7b7b5afdf73 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 13 Oct 2014 23:42:01 -0400 Subject: [PATCH] Improve string performance --- HISTORY.md | 1 + README.md | 40 ++++++++++++++++++++-------------------- index.js | 31 ++++++++++++++++--------------- 3 files changed, 37 insertions(+), 35 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 167fafb..05c6433 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,6 +1,7 @@ unreleased ========== + * Improve string performance * Slightly improve speed for weak ETags over 1KB 1.4.0 / 2014-09-21 diff --git a/README.md b/README.md index 16aaa20..05d0192 100644 --- a/README.md +++ b/README.md @@ -63,10 +63,10 @@ $ npm run-script bench 3 tests completed. 4 tests completed. - buffer - strong x 426,717 ops/sec ±1.34% (181 runs sampled) -* buffer - weak x 1,081,596 ops/sec ±0.32% (196 runs sampled) - string - strong x 235,880 ops/sec ±1.01% (190 runs sampled) - string - weak x 373,234 ops/sec ±0.87% (192 runs sampled) + buffer - strong x 425,962 ops/sec ±1.21% (186 runs sampled) +* buffer - weak x 1,094,538 ops/sec ±0.35% (197 runs sampled) + string - strong x 437,636 ops/sec ±1.31% (183 runs sampled) + string - weak x 316,978 ops/sec ±1.55% (188 runs sampled) > node benchmark/body1-1kb.js @@ -77,10 +77,10 @@ $ npm run-script bench 3 tests completed. 4 tests completed. - buffer - strong x 274,188 ops/sec ±1.17% (192 runs sampled) -* buffer - weak x 298,451 ops/sec ±0.49% (194 runs sampled) - string - strong x 157,331 ops/sec ±2.12% (186 runs sampled) - string - weak x 169,242 ops/sec ±1.51% (188 runs sampled) + buffer - strong x 278,712 ops/sec ±1.00% (193 runs sampled) +* buffer - weak x 300,008 ops/sec ±0.30% (196 runs sampled) + string - strong x 276,016 ops/sec ±1.13% (188 runs sampled) + string - weak x 166,522 ops/sec ±1.47% (192 runs sampled) > node benchmark/body2-5kb.js @@ -91,10 +91,10 @@ $ npm run-script bench 3 tests completed. 4 tests completed. - buffer - strong x 102,624 ops/sec ±0.93% (193 runs sampled) -* buffer - weak x 104,696 ops/sec ±1.17% (190 runs sampled) - string - strong x 59,097 ops/sec ±3.93% (186 runs sampled) - string - weak x 59,202 ops/sec ±4.01% (185 runs sampled) + buffer - strong x 105,233 ops/sec ±0.65% (195 runs sampled) +* buffer - weak x 108,091 ops/sec ±0.81% (194 runs sampled) + string - strong x 102,725 ops/sec ±0.80% (192 runs sampled) + string - weak x 102,649 ops/sec ±0.85% (193 runs sampled) > node benchmark/body3-10kb.js @@ -105,10 +105,10 @@ $ npm run-script bench 3 tests completed. 4 tests completed. - buffer - strong x 54,768 ops/sec ±1.43% (188 runs sampled) -* buffer - weak x 57,393 ops/sec ±1.10% (192 runs sampled) - string - strong x 36,597 ops/sec ±3.81% (179 runs sampled) - string - weak x 35,525 ops/sec ±3.82% (186 runs sampled) + buffer - strong x 59,673 ops/sec ±0.46% (195 runs sampled) +* buffer - weak x 61,525 ops/sec ±0.54% (194 runs sampled) + string - strong x 57,557 ops/sec ±0.62% (194 runs sampled) + string - weak x 58,627 ops/sec ±0.59% (195 runs sampled) > node benchmark/body4-100kb.js @@ -119,10 +119,10 @@ $ npm run-script bench 3 tests completed. 4 tests completed. -* buffer - strong x 6,243 ops/sec ±0.84% (194 runs sampled) -* buffer - weak x 6,312 ops/sec ±0.95% (193 runs sampled) - string - strong x 4,984 ops/sec ±2.21% (191 runs sampled) - string - weak x 5,068 ops/sec ±2.32% (190 runs sampled) + buffer - strong x 6,733 ops/sec ±0.26% (196 runs sampled) +* buffer - weak x 6,920 ops/sec ±0.40% (197 runs sampled) + string - strong x 6,344 ops/sec ±0.47% (193 runs sampled) + string - weak x 6,236 ops/sec ±1.03% (189 runs sampled) ``` ## License diff --git a/index.js b/index.js index ce9787a..bb05eb7 100644 --- a/index.js +++ b/index.js @@ -41,7 +41,6 @@ function etag(entity, options) { throw new TypeError('argument entity is required') } - var isBuffer = Buffer.isBuffer(entity) var isStats = isstats(entity) var weak = options && typeof options.weak === 'boolean' ? options.weak @@ -52,16 +51,13 @@ function etag(entity, options) { return stattag(entity, weak) } - if (!isBuffer && typeof entity !== 'string') { + if (typeof entity !== 'string' && !Buffer.isBuffer(entity)) { throw new TypeError('argument entity must be string, Buffer, or fs.Stats') } - var buf = !isBuffer - ? new Buffer(entity, 'utf8') - : entity var hash = weak - ? weakhash(buf) - : stronghash(buf) + ? weakhash(entity) + : stronghash(entity) return weak ? 'W/"' + hash + '"' @@ -131,15 +127,15 @@ function stattag(stat, weak) { * @api private */ -function stronghash(buf) { - if (buf.length === 0) { +function stronghash(entity) { + if (entity.length === 0) { // fast-path empty return '1B2M2Y8AsgTpgAmY7PhCfg==' } return crypto .createHash('md5') - .update(buf) + .update(entity, 'utf8') .digest('base64') } @@ -151,20 +147,25 @@ function stronghash(buf) { * @api private */ -function weakhash(buf) { - if (buf.length === 0) { +function weakhash(entity) { + if (entity.length === 0) { // fast-path empty return '0-0' } - if (buf.length <= crc32threshold) { + var len = typeof entity === 'string' + ? Buffer.byteLength(entity, 'utf8') + : entity.length + + if (len <= crc32threshold) { // crc32 plus length when it's fast - return buf.length.toString(16) + '-' + crc(buf).toString(16) + // crc(str) only accepts utf-8 encoding + return len.toString(16) + '-' + crc(entity).toString(16) } // use md4 for long strings return crypto .createHash('md4') - .update(buf) + .update(entity, 'utf8') .digest('base64') }