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

process: add nice() function #21675

Closed
wants to merge 7 commits into from
Closed

Conversation

zokker13
Copy link

@zokker13 zokker13 commented Jul 5, 2018

The nice function allows us to fine-tune the process to meet desired
scheduling behavior. If our process needs less schedule time because
it is a long-running one, we can increase the nice value and cause
the scheduler to select the process not so often.

If desired, here's the technical documentation: http://man7.org/linux/man-pages/man2/nice.2.html

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

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. labels Jul 5, 2018
Copy link
Member

@addaleax addaleax left a comment

Choose a reason for hiding this comment

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

Looks pretty good so far … nice :)

@@ -1642,6 +1642,40 @@ This function is only available on POSIX platforms (i.e. not Windows or
Android).
This feature is not available in [`Worker`][] threads.

## process.nice(inc)
<!-- YAML
added: v10.?.?
Copy link
Member

Choose a reason for hiding this comment

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

Can you use REPLACEME as the placeholder here? It gets picked up by release tooling automatically

Copy link
Author

Choose a reason for hiding this comment

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

Done.

// ..only check type if argument is int32
if (!args[0]->IsUndefined()) {
CHECK(args[0]->IsInt32());
inc = args[0]->Int32Value();
Copy link
Member

Choose a reason for hiding this comment

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

Can you use args[0].As<Int32>()->Value()? ->Int32Value() is an operation that potentially performs a type conversion, but that’s unnecessarily complex, since we already know that it’s an Int32

Copy link
Author

Choose a reason for hiding this comment

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

Sounds great and it's done, thanks!

@@ -98,6 +104,18 @@ function setupPosixMethods(_initgroups, _setegid, _seteuid,
}
};

function validateInc(inc) {
const tInc = typeof inc;
Copy link
Member

Choose a reason for hiding this comment

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

Can you inline typeof inc here? The engine is generally better at recognizing that pattern and can eliminate the temporary string you’d be creating here

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for the deep insights. It is fixed.

validateInt32(inc, 'nice');
return _nice(inc);
} else if (tInc === 'undefined') {
return _nice(inc);
Copy link
Member

Choose a reason for hiding this comment

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

I think it’s a bit confusing to mix validation and the actual calls to _nice … could you separate them?

Copy link
Author

Choose a reason for hiding this comment

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

Split them up.:)

@addaleax addaleax added child_process Issues and PRs related to the child_process subsystem. semver-minor PRs that contain new features and should be released in the next minor version. process Issues and PRs related to the process subsystem. notable-change PRs with changes that should be highlighted in changelogs. and removed lib / src Issues and PRs related to general changes in the lib or src directory. child_process Issues and PRs related to the child_process subsystem. labels Jul 5, 2018
@addaleax
Copy link
Member

addaleax commented Jul 5, 2018

Also: Your author name in this commit is given as “zokker13”. Is that intended or do you prefer to be listed (changelog, git log, AUTHORS file) with some other name? People typically prefer their full name, but ultimately it’s up to you.

The higher the nice value of the process, the nicer the process and the less
time is given by the scheduler.

You can get the current nice value by passing 0 or nothing to the method.

This comment was marked as resolved.

@zokker13
Copy link
Author

zokker13 commented Jul 5, 2018

@addaleax Thanks for the review and the lightning fast response. Added your requests. Hope that "fixup" -commit is appropriate.

Copy link
Member

@addaleax addaleax left a comment

Choose a reason for hiding this comment

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

Great, thanks!

return _nice(inc);
} else if (tInc === 'undefined') {
return _nice(inc);
} else if (typeof inc === 'undefined') {
Copy link
Member

@devsnek devsnek Jul 5, 2018

Choose a reason for hiding this comment

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

you can just combine this with the below

function validateInc(inc) {
  if (typeof inc === 'number') {
    validateInt32(inc, 'nice');
  } else if (inc !== undefined) {
    throw new ERR_INVALID_ARG_TYPE('nice', ['number', 'undefined'], inc);
  }
}

Copy link
Author

Choose a reason for hiding this comment

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

Nice catch, totally missed that!
Here it is: 655894e745de20829ff40ee330557da1305f9c7e

@addaleax
Copy link
Member

addaleax commented Jul 5, 2018

CI: https://ci.nodejs.org/job/node-test-pull-request/15747/

As a heads up, our rules will require this PR to stay open for 72 hours so people have a chance to weigh in, and you may have to update this one or two times more during that time. But as first PRs go, this is definitely a first-class example. :)

You can get the current nice value by passing 0 or nothing to the method.

Unless you have super user permissions, you can only increase your nice value.
Though, it is also possible to increase the priority if a limit (RLIMIT_NICE)
Copy link
Member

Choose a reason for hiding this comment

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

This is a sentence fragment. You can make it a complete sentence by removing Though,.

Copy link
Contributor

@mscdex mscdex Jul 5, 2018

Choose a reason for hiding this comment

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

For those not familiar with the 'nice' system, the two different uses of 'increase' here might be confusing. At the very least it would be a good idea to note that increasing the 'nice' value means lowering the process priority. This is hinted at in the paragraph above this one, but I still think using 'increase' back to back here could confuse some people.

Copy link
Author

Choose a reason for hiding this comment

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

I kinda changed the entire thing: a099642629b36e908c5114227c4fd8e9c18cc12f

Though, it is also possible to increase the priority if a limit (RLIMIT_NICE)
is set. (See getrlimit(2).)

**NOTE**: Once you incremented your niceness, you can no longer reduce it!
Copy link
Member

Choose a reason for hiding this comment

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

Please remove **NOTE**:, the exclamation point, and use of you.

Maybe this?:

The nice value can be increased only. It can not be decreased.

...or...

The nice value can never be decreased except by the super user.

...or something like that.

Copy link
Author

Choose a reason for hiding this comment

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

Changed in a way that is (hopefully) better readable: a099642629b36e908c5114227c4fd8e9c18cc12f

@Trott
Copy link
Member

Trott commented Jul 5, 2018

Hi, @zokker13! Welcome and thanks for the PR! I have two requests for the documentation you've added:

  • Don't use **NOTE**:. If there's something important to say, just say it.

  • Don't use you in the docs.

These (well, the second one) are noted in doc/STYLE_GUIDE.md.

@Trott
Copy link
Member

Trott commented Jul 5, 2018

Feels notable enough that pinging @nodejs/tsc seems appropriate.

Also pinging @nodejs/documentation for any other comments on the docs.

```

This function is only available on POSIX platforms (i.e. not Windows or
Android).
Copy link
Contributor

Choose a reason for hiding this comment

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

This sentence is confusing as Android is about as POSIX compliant as Linux is. It would be better to leave that part out and just say that the function is not available on Windows or Android.

Copy link
Author

Choose a reason for hiding this comment

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

I added Android support for this PR: a099642629b36e908c5114227c4fd8e9c18cc12f

added: REPLACEME
-->

* `inc` {integer} The new nice value for the process.
Copy link
Contributor

Choose a reason for hiding this comment

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

We should include return value information here since this function always returns a value.

Copy link
Author

Choose a reason for hiding this comment

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

Check. a099642629b36e908c5114227c4fd8e9c18cc12f

@mscdex
Copy link
Contributor

mscdex commented Jul 5, 2018

Is it not possible to somehow bridge nice() and Windows' priority API via libuv?

Also, from what I'm reading, Android does support nice() (which is currently(?) just a wrapper around their own setpriority()).

@Fishrock123
Copy link
Member

Fishrock123 commented Jul 6, 2018

Does this work on non-linuxies? I also wonder if the underlying impl isn’t better suited for libuv.

@zokker13
Copy link
Author

zokker13 commented Jul 6, 2018

@mscdex Hey,
wrapping nice for Windows seems a bit odd to me. In Windows, we have those 6'ish different process priorities we might set. It doesn't really compare to the way nice() works since we merely add increment steps there. But I'll check out libuv and see how they solve similar issues later this day.
Can't really say anything about Android though. Could you share your find to the docs?

@Fishrock123 Yes, it should work for various POSIX compliant OS'. There are subtle differences between them though. But those differences are limited to the range of the niceness. So perhaps a reference to the min/max niceness would be fitting and convenient to the user (or at least a documentation).

@gireeshpunathil
Copy link
Member

[ I am just thinking aload here, please don't consider as a negative remark on the PR. ]

are there any benchmarks that provide insights on scheduling behavior and its implications on the workload with default priority? I believe most of the UNIX schedulers have special optimizations for I/O workload, so wondering whether manual modification will influence the OS logic and thereby the overall performance positively or negatively.

Also wondering about the characteristics of stream velocity / backpressure etc. under a cluster, child process, IPC toppologies when processes are running with manually preset scheduling priorities.

If we don't have these info or cannot determine, it would be worthwhile considering writing caveats in the doc (or else we can get unwanted issues that complain about not getting desired througput after altering the nice etc.) on these lines: the overall efficiency of Node programs when catering to highly interactive workloads depend on peer end points resident in the host or otherwise. So altering the nice value of the process should be performed carefully, only after running your performance benchmark under full load and realizing any desired improvements.

@mscdex
Copy link
Contributor

mscdex commented Jul 6, 2018

Hey, wrapping nice for Windows seems a bit odd to me. In Windows, we have those 6'ish different process priorities we might set. It doesn't really compare to the way nice() works since we merely add increment steps there.

I imagine someone at some point will want the Windows equivalent in core because process.nice() exists for non-Windows. If we can find a way to support it from the get-go, that would be better. Maybe we don't call it nice() if we support Windows with the same function. Or perhaps we support it in some other way, via a namespace or something else.

Can't really say anything about Android though. Could you share your find to the docs?

@zokker13 https://android.googlesource.com/platform/bionic.git/+/master/libc/upstream-netbsd/lib/libc/gen/nice.c

@addaleax
Copy link
Member

addaleax commented Jul 6, 2018

@gireeshpunathil I don’t necessarily think it’s our job to talk about these things in the docs for nice(). I don’t know if you have increasing or decreasing niceness in mind, but the former will be more common (simply because it doesn’t require privileges), and you generally only do that if you don’t really care about performance all that much.

@gireeshpunathil
Copy link
Member

ok, sure!

the specified permissions are set). (See getrlimit(2).)

```js
if (process.platform !== 'win32') {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think having this is necessary, especially since we already document Windows is not supported below this example.

if (_setgid !== undefined) {
setupPosixMethods(_initgroups, _setegid, _seteuid,
_setgid, _setuid, _setgroups);
}

process.nice = function nice(inc) {
if (process.platform === 'win32') {
Copy link
Contributor

@mscdex mscdex Jul 7, 2018

Choose a reason for hiding this comment

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

Perhaps change this so the platform check is only run once when this file is evaluated, since the process platform will not change during runtime. Example:

if (process.platform === 'win32') {
  process.nice = function nice(inc) {
    throw new ERR_METHOD_NOT_IMPLEMENTED('nice()');
  };
} else {
  process.nice = function nice(inc) {
    validateInc(inc);
    return _nice(inc);
  };
}

or something similar

const assert = require('assert');

if (common.isWindows || !common.isMainThread) {
assert.strictEqual(process.nice, undefined);
Copy link
Contributor

@mscdex mscdex Jul 7, 2018

Choose a reason for hiding this comment

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

This is no longer valid since we're now throwing.

However, I feel like we should just call common.skip() with an appropriate message to make it obvious that we're not testing the real implementation.

}
);

[null, false, true, {}, [], () => {}, 'text'].forEach((val) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

How about also testing that passing '0' or undefined results in a finite integer being returned?

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, we might want to test that something like process.nice(1) works as expected.

@zokker13
Copy link
Author

zokker13 commented Jul 7, 2018

Mh.. okay guys, I thought about having a more neutral function (say getpriority/setpritority) in favor of the nice function. The reason is that it doesn't really have a future on Windows and when we later add a functionality to set the priority cross-platform, nobody would use the posix function anyway.
That way the API is more clear and fewer obstacles are placed.

So I'd like to close this for now, go visit the libuv fellows and come back to implement a neutral call here.

@addaleax
Copy link
Member

addaleax commented Jul 7, 2018

@zokker13 I think this PR is still in pretty good shape (I personally disagree about being inconsistent with other functions re: Windows, but, oh well). Can we mark this PR as in progress just so it doesn’t get merged, you try to work up something for libuv, and if that doesn’t pan out, we can continue where we left here?

The nice function allows us to fine-tune the process to meet desired
scheduling behavior. If our process needs less schedule time because
it is a long-running one, we can increase the nice value and cause
the scheduler to select the process not so often.
@zokker13
Copy link
Author

zokker13 commented Jul 7, 2018

@addaleax Ya, that sounds fine, thanks. I think the discussion alone is a good reason to go that route. Rebased just to be sure.

Perhaps @cjihrig would be so kind to guide me to the correct libuv location? The node structure is more familiar to me but libuv seems a bit mixed.

@cjihrig
Copy link
Contributor

cjihrig commented Jul 7, 2018

would be so kind to guide me to the correct libuv location?

You'd probably want to target https://github.com/libuv/libuv/blob/v1.x/src/unix/core.c and https://github.com/libuv/libuv/blob/v1.x/src/win/util.c.

@addaleax addaleax added the wip Issues and PRs that are still a work in progress. label Jul 8, 2018
cjihrig added a commit to cjihrig/libuv that referenced this pull request Aug 15, 2018
Refs: nodejs/node#21675
PR-URL: libuv#1945
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
cjihrig added a commit to libuv/libuv that referenced this pull request Aug 15, 2018
Refs: nodejs/node#21675
PR-URL: #1945
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
cjihrig added a commit to cjihrig/node that referenced this pull request Aug 20, 2018
Notable changes:
- Restores compatibility with the old IPC protocol.
- Adds uv_open_osfhandle().
- Adds uv_os_{get,set}priority().

PR-URL: nodejs#22365
Fixes: nodejs#21671
Fixes: nodejs#15433
Refs: nodejs#21675
Refs: nodejs/node-addon-api#304
Refs: nodejs/abi-stable-node#318
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
targos pushed a commit that referenced this pull request Aug 21, 2018
Notable changes:
- Restores compatibility with the old IPC protocol.
- Adds uv_open_osfhandle().
- Adds uv_os_{get,set}priority().

PR-URL: #22365
Fixes: #21671
Fixes: #15433
Refs: #21675
Refs: nodejs/node-addon-api#304
Refs: nodejs/abi-stable-node#318
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
targos pushed a commit that referenced this pull request Sep 3, 2018
Notable changes:
- Restores compatibility with the old IPC protocol.
- Adds uv_open_osfhandle().
- Adds uv_os_{get,set}priority().

PR-URL: #22365
Fixes: #21671
Fixes: #15433
Refs: #21675
Refs: nodejs/node-addon-api#304
Refs: nodejs/abi-stable-node#318
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
@Fishrock123
Copy link
Member

Superseded by the now-merged #22407

MylesBorins pushed a commit to MylesBorins/node that referenced this pull request Nov 5, 2018
Notable changes:
- Restores compatibility with the old IPC protocol.
- Adds uv_open_osfhandle().
- Adds uv_os_{get,set}priority().

PR-URL: nodejs#22365
Fixes: nodejs#21671
Fixes: nodejs#15433
Refs: nodejs#21675
Refs: nodejs/node-addon-api#304
Refs: nodejs/abi-stable-node#318
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
MylesBorins pushed a commit that referenced this pull request Nov 11, 2018
Notable changes:
- Restores compatibility with the old IPC protocol.
- Adds uv_open_osfhandle().
- Adds uv_os_{get,set}priority().

Backport-PR-URL: #24103
PR-URL: #22365
Fixes: #21671
Fixes: #15433
Refs: #21675
Refs: nodejs/node-addon-api#304
Refs: nodejs/abi-stable-node#318
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. notable-change PRs with changes that should be highlighted in changelogs. process Issues and PRs related to the process subsystem. semver-minor PRs that contain new features and should be released in the next minor version. wip Issues and PRs that are still a work in progress.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet