Skip to content
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

buffer: port byteLengthUtf8 to JavaScript #18356

Closed
wants to merge 1 commit into from

Conversation

indutny
Copy link
Member

@indutny indutny commented Jan 24, 2018

Please don't land this PR yet. There is a missing V8 optimization, that is going to be available soon
in V8 6.6.


Prior to this change the majority of the time spent when
calling Buffer.byteLength was spent on crossing JS->C++ boundary. This
change move the function to JavaScript, making it much faster.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines
Affected core subsystem(s)

buffer

@nodejs-github-bot nodejs-github-bot added buffer Issues and PRs related to the buffer subsystem. c++ Issues and PRs that require attention from people who are familiar with C++. labels Jan 24, 2018
Prior to this change the majority of the time spent when
calling `Buffer.byteLength` was spent on crossing JS->C++ boundary. This
change move the function to JavaScript, making it much faster.
@indutny indutny force-pushed the feature/js-buffer-length-utf8 branch from 2c35736 to de2287e Compare January 24, 2018 19:28
@jasnell
Copy link
Member

jasnell commented Jan 24, 2018

Performance boost I assume?

@indutny
Copy link
Member Author

indutny commented Jan 24, 2018

@jasnell forgot to write about it. It is 2x faster on small strings, but is slower on large ones. This is the reason for awaiting for v8 update.

@jasnell
Copy link
Member

jasnell commented Jan 24, 2018

If the perf loss on the large ones is significant, perhaps split the difference and use the js method for short ones and fallback on longer?

@indutny
Copy link
Member Author

indutny commented Jan 24, 2018

Perhaps, but I'd rather wait for V8 update. We've been living with C++ code for awhile now.

@joyeecheung joyeecheung added the wip Issues and PRs that are still a work in progress. label Jan 24, 2018
@indutny
Copy link
Member Author

indutny commented Jan 24, 2018

Added expected V8 version.

// NOTE: 0 <= code <= 0xffff
var code = string.charCodeAt(i);
if (code <= 0x7f) {
len++;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

len += 1; for consistency with line 348.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking 😉

@indutny
Copy link
Member Author

indutny commented Mar 7, 2018

Looks like this might be ready after #19201 lands.

@indutny
Copy link
Member Author

indutny commented Mar 7, 2018

Hm... it is still slow even on V8 6.6. cc @bmeurer

Here's the benchmark that I used: https://gist.github.com/indutny/0fe9a3ed3b93d558a60deacefc37e378 . The results are:

c++: 7.052ms
js: 6.731ms
c++: 235.835ms
js: 5739.299ms

@bmeurer
Copy link
Member

bmeurer commented Mar 8, 2018

You need to pass --nountrusted-code-mitigations to disable the Spectre mitigations, which also affect String#charCodeAt. But even then the C++ code is going to be significantly faster. I'm not sure we can fix the difference here.

@indutny
Copy link
Member Author

indutny commented Mar 8, 2018

@bmeurer tbh, I don't see a reason for it to be slow. The performance seems to be dependent on string flattening, which apparently doesn't happen in JS case. Could it potentially happen at all?

@bmeurer
Copy link
Member

bmeurer commented Mar 8, 2018

@indutny The reason is that String#charCodeAt() has to dispatch on string type all the time (potentially 8 different types for the "fast case"), whereas the C++ code just accesses the character data. We could try to make TurboFan a bit smarter here if we find a way to do the flattening (which is indeed happening here) in the peeled loop iteration only and then have only sequential one-byte string access inside the actual loop. But that's work that needs to be done and I'm a bit worried that we over-optimize for the particular example.

@bmeurer
Copy link
Member

bmeurer commented Mar 8, 2018

BTW V8 tip-of-tree should be faster already thanks to the recent work by @sigurdschneider.

@indutny
Copy link
Member Author

indutny commented Mar 8, 2018

@bmeurer thank you!

@jasnell and @nodejs/collaborators looks like it'd best to close this.

@bmeurer
Copy link
Member

bmeurer commented Mar 8, 2018

Not saying it's not worth it, but it's definitely not high priority.

Did you check with tip-of-tree? And --nountrusted-code-mitigations?

@indutny
Copy link
Member Author

indutny commented Mar 8, 2018

@bmeurer I checked --nountrusted-code-mitigations, and although it was faster - it was still significantly slower than C++. Didn't check tip-of-tree yet.

Copy link
Member

@srl295 srl295 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems ok (did not check the math in detail)…  might also compare to http://source.icu-project.org/repos/icu/trunk/icu4c/source/common/unicode/utf8.h which has been highly optimized

@BridgeAR
Copy link
Member

Should this stay open? It seems like the JS implementation can not get as fast as the C++ implementation. Ping @indutny

@BridgeAR
Copy link
Member

Closing as this does not seem like it is the right approach in JS.

@indutny please reopen in case you disagree and want to continue working on this.

@BridgeAR BridgeAR closed this Apr 16, 2018
@indutny
Copy link
Member Author

indutny commented Apr 16, 2018

I think we could potentially apply it to short strings. Anyone up to do some benchmarks?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
buffer Issues and PRs related to the buffer subsystem. c++ Issues and PRs that require attention from people who are familiar with C++. wip Issues and PRs that are still a work in progress.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants