FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

buffer: move checkFloat from lib into src by matthewloring · Pull Request #3763 · nodejs/node · GitHub

/ node Public

buffer: move checkFloat from lib into src - #3763

Closed
matthewloring wants to merge 1 commit into
nodejs:masterfrom
matthewloring:buffer-check
Closed

buffer: move checkFloat from lib into src#3763
matthewloring wants to merge 1 commit into
nodejs:masterfrom
matthewloring:buffer-check

Conversation

Copy link
Copy Markdown

The type and range checks performed by this function can be done more
efficiently in native code.

/cc @trevnorris

Comment thread src/node_buffer.cc Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

You can avoid double negative stuff here, if you simply name it as should_assert or something like that.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

It is named this way to maintain consistency with the existing JS api.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

@matthewloring I think the convention in C++ is to use snake case for local variables and I am more interested in something like this

bool should_assert = !args[3]->BooleanValue();
...
if (should_assert) {
    ...
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

It is convention to use snake_case in native code, and since I've been bitten in the butt by it before (in buffer code actually) I'll have to agree with @thefourtheye's observation of avoiding double negative is a better option.

Also, we'll need to do some benchmarking on BooleanValue(). Last time I used it (way way back in v0.10) the performance was bad enough that we actually prefixed the check with IsUndefined(). So may look something like this:

bool should_assert = !args[3]->IsUndefined() && !args[3]->BooleanValue();

Think that's right, but it's getting late.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I believe the condition should be args[3]->IsUndefined() || !args[3]->BooleanValue(). Alternatively, we could use !! on the JS side to ensure we only get booleans at this point the same way the other arguments are type coerced value = +value; offset = offset >>> 0;. Do you have a preference between these?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

In the mean time, I've fixed the case and negation issues here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

These v8::Value::XValue methods are scheduled for deprecation in favor of the Maybe versions.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I've updated the value accesses in this function to use the new version. It looks like the non-Maybe versions are still used elsewhere throughout the file.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

@matthewloring From my distant memory it was indeed faster to coerce noAssert in JS. Then you can do a simple IsTrue() check, and drop the other two.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

@trevnorris I've moved the boolean coercion into JS.

thefourtheye added the buffer Issues and PRs related to the buffer subsystem. label Nov 11, 2015
Comment thread src/node_buffer.cc Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Drop the CHECK_LE below the conditional check. We still want to abort to prevent writing to memory bits we don't have control over.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

NM this comment. Logic will change w/ another upcoming PR.

Copy link
Copy Markdown
Contributor

@matthewloring Awesome job. Thanks much for taking care of this. Has been one of those changes in my backlog that never taken the time to get to. Since this is all about micro-optimization (we'll only be shaving off 20ns or so here) there may be some experimentation we'll need to do

Copy link
Copy Markdown
Contributor

@matthewloring There's going to be a collision with #3767. It only touches the location where you removed the CHECK_LE. Mind if I proceed with that one, the we rebase this one and continue to make things fast?

EDIT: Ref'd issue was this one. Has been fixed.

Copy link
Copy Markdown
Author

@trevnorris It should be an easy merge conflict to resolve. You're welcome to land #3767.

Comment thread lib/buffer.js Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

sorry, minor nit: do the boolean coercion in the call itself. e.g. writeFloatBE(this, val, offset, !!noAssert);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Inlined.

Copy link
Copy Markdown
Contributor

Looks great. As soon as I can land the previously mentioned patch, get this rebased and CI is happy we'll be good to land.

LGTM.

Comment thread src/node_buffer.cc Outdated

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Why does this function take the T parameter? T is used as the return type for v8::Value::NumberValue::FromMaybe, which returns a double.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

val may either be a double or float.

trevnorris self-assigned this Nov 12, 2015

jasnell commented Nov 12, 2015

Copy link
Copy Markdown
Member

LGTM

jasnell commented Nov 12, 2015

Copy link
Copy Markdown
Member

@trevnorris ... as an optimization, I'm inclined not to flag this for LTS but would like your input on that.

Copy link
Copy Markdown
Contributor

@jasnell Sounds reasonable. I think this is low risk, but also not critical.

jasnell commented Nov 14, 2015

Copy link
Copy Markdown
Member

Copy link
Copy Markdown
Author

Looks like this may be integer overflow on 32-bit architectures? I can verify and put together a fix.

Copy link
Copy Markdown
Contributor

@matthewloring ping me when you have a fix, or have a question, and will run CI again.

Copy link
Copy Markdown
Author

@trevnorris I've added the lower bounds check which I believe to fix the problem but do not have a centos 32 vm to reproduce the initial failure on. Are there existing overflow prevention checks elsewhere inside buffer that I should emulate or does the added check CHECK_NOT_OOB(offset + sizeof(T) >= sizeof(T)); at line 745 seem good? If so, it's ready for another CI.

Copy link
Copy Markdown
Contributor

Copy link
Copy Markdown
Author

The test-crypto-dh.js timeouts are happening on a few machines but it should be unrelated.

Copy link
Copy Markdown
Contributor

@matthewloring Just landed the other conflicting PR. Mind rebasing on latest master?

The other PR alerted me to the specific wording in the current documentation:

Set noAssert to true to skip validation of value and offset. This means
that value may be too large for the specific function and offset may be
beyond the end of the buffer leading to the values being silently dropped.

So I believe if noAssert is set and the offset is beyond the bound of the buffer we simply return early. Though I'd still leave in that specific CHECK just to make sure any future modifications don't accidentally allow writing beyond memory bounds.

Copy link
Copy Markdown
Author

@trevnorris I've rebased and reinserted the CHECK_LE just as a failsafe. Should be good to go.

Copy link
Copy Markdown
Contributor

Copy link
Copy Markdown
Author

Failures (mostly crypto timeouts) should be unrelated flakes.

Copy link
Copy Markdown
Contributor

@matthewloring We'll need to do some investigation. The call is slower than it is now. This is the fun part. :) I'll update if I find any details. Here's a simple script I'm using:

'use strict';
const ITER = 1e7;
var b = new Buffer(8);
var t = process.hrtime();
for (var i = 0; i < ITER; i++) {
  b.writeDoubleLE(0, 0, true);
}
t = process.hrtime(t);
console.log(((t[0] * 1e9 + t[1]) / ITER).toFixed(1) + ' ns/op');

(note: this is fine b/c the call into native isn't affected by the optimizing compiler like JS would be)

Copy link
Copy Markdown
Author

Hmm, I can look into this as well.

Copy link
Copy Markdown
Author

It looks like at least part of the slow down is caused by the new maybe versions of NumberValue and Uint32Value. I see ~53 ns/op with the maybe versions compared to ~46 ns/op with the old versions of NumberValue and Uint32Value and ~44 ns/op with the checks remaining in JS (at master).

Copy link
Copy Markdown
Contributor

@matthewloring Here's a diff gaining back the lost performance: https://gist.github.com/trevnorris/3bce2822893a98e9d971

Sorry, this is where writing performant code makes things look worse.

Copy link
Copy Markdown
Contributor

The new Maybe versions definitely aren't helping. Also getting the values out (e.g. NumberValue() are taking longer than I'd expect).

The type and range checks performed by this function can be done more
efficiently in native code.

Copy link
Copy Markdown
Author

That change brings script down to ~42 for me. I've applied your change.

Copy link
Copy Markdown
Contributor

Copy link
Copy Markdown
Author

Only failure is a child process fork connection reset, seems good to me.

Copy link
Copy Markdown
Contributor

Thanks much! Landed in 22478d3.

trevnorris pushed a commit that referenced this pull request Nov 20, 2015
The type and range checks performed by this function can be done more
efficiently in native code.

PR-URL: #3763
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
trevnorris closed this Nov 20, 2015
rvagg pushed a commit that referenced this pull request Dec 5, 2015
The type and range checks performed by this function can be done more
efficiently in native code.

PR-URL: #3763
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
rvagg mentioned this pull request Dec 17, 2015

rvagg commented Jan 15, 2016

Copy link
Copy Markdown
Member

Marking with dont-land-on-v4.x but noting that above discussion suggests that this could be a candidate if we changed our risk profile for LTS.

matthewloring deleted the buffer-check branch February 25, 2016 19:53
ChALkeR added the performance Issues and PRs related to the performance of Node.js. label Mar 8, 2016
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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. performance Issues and PRs related to the performance of Node.js.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants


Back | FazBrowse Home | New Git URL