New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

benchmark: reduce string concatenations #12455

Closed
wants to merge 4 commits into
base: master
from

Conversation

Projects
None yet
8 participants
@vsemozhetbyt
Copy link
Member

vsemozhetbyt commented Apr 17, 2017

Checklist
Affected core subsystem(s)

benchmark

I. Presupposition

String concatenations usually increase syntax noise and add confusion (a reader often has to check if string concatenation or number addition is intended). Moreover, it seems this method is not optimal performance-wise.

II. Cases

This PR aims two cases of string concatenation:

  • multipart concatenations with variable interpolation ('a' + b + 'c');
  • type coercion to String ('' + notString). This approach, while idiomatic, is not most declarative.

III. Performance

The added benchmark compares these variants:

  • 'a' + b + 'c' vs ['a', b, 'c'].join('') vs `a${b}c`
  • String(notString) vs '' + notString vs `${notString}`

Results with Node.js 8.0.0 rc:

es\string-concatenations.js mode="multi-concat"       n=1000:   909,455.5180758832
es\string-concatenations.js mode="multi-join"         n=1000:   290,896.9895943238
es\string-concatenations.js mode="multi-template"     n=1000: 2,620,236.0832711025

es\string-concatenations.js mode="to-string-string"   n=1000: 6,020,179.642160523
es\string-concatenations.js mode="to-string-concat"   n=1000: 1,141,656.7723079734
es\string-concatenations.js mode="to-string-template" n=1000: 5,700,376.794906143

IV. Commits

  1. Reduce string concatenations: replace concatenations with template literals, rewrap,
    String.prototype.repeat(), String(). Some replacements do not add indisputable readability gain, but I tried to be consistent.

  2. Add a benchmark for string concatenations vs counterparts.

  3. This commit is added here to avoid PR race condition and merge conflicts. It fixes an URL in _http-benchmarkers.js (removes duplicate hash symbol).

  4. This commit is added here to avoid PR race condition and merge conflicts. It fixes an evident typo in _http-benchmarkers.js: Error() constructor has only one parameter, while callback() has 5 (compare a previous call and callback() signature).

All changed files were minimally tested. CI for linting and new tests concerning benchmarks will be launched.

@vsemozhetbyt

This comment has been minimized.

Copy link
Member Author

vsemozhetbyt commented Apr 17, 2017

benchmark/assert/deepequal-typedarrays.js Outdated
'Uint32Array',
'Float32Array',
'Float64Array',
'Uint8ClampedArray',

This comment has been minimized.

@mscdex

mscdex Apr 17, 2017

Contributor

Indented too far.

benchmark/_http-benchmarkers.js Outdated
'https://github.com/nodejs/node/blob/master/doc/guides/writing-and-running-benchmarks.md##http-benchmark-requirements ' +
'for further instructions.'));
callback(new Error(`Could not locate required http benchmarker. See ${
requirementsURL} for further instructions.`));

This comment has been minimized.

@mscdex

mscdex Apr 17, 2017

Contributor

Why the odd indentation here and elsewhere? Shouldn't they line up with the beginning of the string?

This comment has been minimized.

@vsemozhetbyt

vsemozhetbyt Apr 17, 2017

Author Member

I've tried to stress the subordinate state of the next part. I'll try to decrease indentation.

`| ${fraction(completedRunsForFile, runsPerFile)} runs ` +
`| ${fraction(completedConfig, scheduledConfig)} configs]` +
`: ${caption} `;
return `[${getTime(diff)}|% ${

This comment has been minimized.

@mscdex

mscdex Apr 17, 2017

Contributor

FWIW I'm not particularly a fan of this style to avoid the extra spacing.

This comment has been minimized.

@vsemozhetbyt

vsemozhetbyt Apr 17, 2017

Author Member

Can you elaborate?

This comment has been minimized.

@mscdex

mscdex Apr 17, 2017

Contributor

Using ${ followed by a newline to avoid including spaces due to indentation.

@vsemozhetbyt vsemozhetbyt force-pushed the vsemozhetbyt:bench-templates branch Apr 17, 2017

@vsemozhetbyt

This comment has been minimized.

Copy link
Member Author

vsemozhetbyt commented Apr 17, 2017

Some indentation was reduced. New CI: https://ci.nodejs.org/job/node-test-pull-request/7435/

@@ -54,9 +54,3 @@ function main(conf) {
}
bench.end(n);
}

function buildString(str, times) {

This comment has been minimized.

@benjamingr

benjamingr Apr 17, 2017

Member

It's funny we even had a recursive implementation :D

This comment has been minimized.

@vsemozhetbyt

vsemozhetbyt Apr 17, 2017

Author Member

Yeah, I am even sorry to retire it)

' buff.' + fn + '(i, 0, ' + JSON.stringify(noAssert) + ');',
'}'
].join('\n'));
var testFunction = new Function('buff', `

This comment has been minimized.

@benjamingr

benjamingr Apr 17, 2017

Member

much nicer

benchmark/common.js Outdated
@@ -44,7 +44,7 @@ Benchmark.prototype._parseArgs = function(argv, configs) {
for (const arg of argv) {
const match = arg.match(/^(.+?)=([\s\S]*)$/);
if (!match || !match[1]) {
console.error('bad argument: ' + arg);
console.error(`bad argument: ${arg}`);

This comment has been minimized.

@benjamingr

benjamingr Apr 17, 2017

Member

console.error('bad argument:', arg) ?

This comment has been minimized.

@vsemozhetbyt

vsemozhetbyt Apr 17, 2017

Author Member

I think this would imply we need inspect() for arg (as we do for Error objects), while arg is a simple string.

@@ -30,14 +30,14 @@ function main(conf) {
var len = +conf.millions * 1e6;
var clazz = conf.buf === 'fast' ? Buffer : require('buffer').SlowBuffer;
var buff = new clazz(8);
var fn = 'read' + conf.type;
var fn = `read${conf.type}`;

This comment has been minimized.

@jasnell

jasnell Apr 17, 2017

Member

just a reminder that this will make it impossible to run these benchmarks to compare against anything older than 4.0.0. That's not an objection, by any means.

This comment has been minimized.

@vsemozhetbyt

vsemozhetbyt Apr 17, 2017

Author Member

Yes, but there were many other template literals in benchmarks before this edition, including common.js.

This comment has been minimized.

@mscdex

mscdex Apr 17, 2017

Contributor

At this point I don't think it really matters. I can't see anyone wanting to run the benchmarks for v0.10 or v0.12 anymore, especially since it wouldn't really do any good (it's not as if the V8 team can/will revert to v0.10/v0.12-era V8 code if there is a performance issue in node v4.x+).

This comment has been minimized.

@jasnell

jasnell Apr 17, 2017

Member

Yep, as I said, it's not an objection. Just noting the change. We may want to let folks know just so that they're aware.

This comment has been minimized.

@joyeecheung

joyeecheung Apr 21, 2017

Member

I think a lot of benchmarks don't run on v4.x or older anyways...I've seen people on IRC
asking why some benchmark doesn't run and turns out they are using v4.x to run it

@vsemozhetbyt vsemozhetbyt referenced this pull request Apr 28, 2017

Closed

test: reduce string concatenations #12735

3 of 24 tasks complete

@evanlucas evanlucas referenced this pull request May 1, 2017

Merged

v7.10.0 proposal #12775

evanlucas added a commit that referenced this pull request May 1, 2017

benchmark: add benchmark for string concatenations
PR-URL: #12455
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>

evanlucas added a commit that referenced this pull request May 2, 2017

benchmark: add benchmark for string concatenations
PR-URL: #12455
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>

vsemozhetbyt added a commit to vsemozhetbyt/node that referenced this pull request May 5, 2017

vsemozhetbyt added a commit that referenced this pull request May 5, 2017

test: reduce string concatenations
PR-URL: #12735
Refs: #12455
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>

anchnk added a commit to anchnk/node that referenced this pull request May 6, 2017

test: reduce string concatenations
PR-URL: nodejs#12735
Refs: nodejs#12455
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>

@jasnell jasnell referenced this pull request May 11, 2017

Closed

8.0.0 Release Proposal #12220

vsemozhetbyt added a commit to vsemozhetbyt/node that referenced this pull request Jun 23, 2017

test: reduce string concatenations
PR-URL: nodejs#12735
Refs: nodejs#12455
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>

MylesBorins added a commit that referenced this pull request Jul 10, 2017

test: reduce string concatenations
PR-URL: #12735
Refs: #12455
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>

MylesBorins added a commit that referenced this pull request Jul 10, 2017

test: reduce string concatenations
Backport-PR-URL: #13835
PR-URL: #12735
Refs: #12455
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>

MylesBorins added a commit that referenced this pull request Jul 11, 2017

test: reduce string concatenations
Backport-PR-URL: #13835
PR-URL: #12735
Refs: #12455
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment