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

util: change inspect depth default #17907

Closed
wants to merge 7 commits into from

Conversation

BridgeAR
Copy link
Member

Right now the defaults for util.inspect are often not ideal. This is a first step to improve those. I tried not to break to much and keep the current behavior for the repl and console.

Refs: #12693

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)

util, console

@nodejs-github-bot nodejs-github-bot added console Issues and PRs related to the console subsystem. repl Issues and PRs related to the REPL subsystem. util Issues and PRs related to the built-in util module. labels Dec 28, 2017
@BridgeAR BridgeAR added the semver-major PRs that contain breaking changes and should be released in the next major version. label Dec 28, 2017
@@ -317,7 +317,9 @@ Object.defineProperty(inspect, 'defaultOptions', {
if (options === null || typeof options !== 'object') {
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'options', 'Object');
}
Object.assign(inspectDefaultOptions, options);
Copy link
Member

Choose a reason for hiding this comment

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

Any reason for not using _extend?

Copy link
Member Author

Choose a reason for hiding this comment

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

The type check has to be done again in that case.

Copy link
Member

Choose a reason for hiding this comment

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

I doubt it will add a noticeable overhead but yes it makes sense.

Copy link
Member

Choose a reason for hiding this comment

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

  1. Do we actually care about the performance of inspection? I thought we didn’t.
  2. Same concern here as @lpinca. This is quite literally reinventing the wheel, and type checks for object are quite fast in modern V8.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated the use _extend as it will still be faster than Object.assign

Copy link
Member Author

Choose a reason for hiding this comment

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

About the performance - just recently I heard that inspect came up in a flamegraph. Seems like people use it a lot. I am aware that setting the default options will not be a big thing but the first implementation (not changing inspect for console.*) used it a lot and that is why I decided to optimize it as well.

@silverwind
Copy link
Contributor

Not sure I like the complexity introduced here. Given that this is already flagged as semver-major, why not update it to 5 (I'd leave that value open to discussion, but it's certainly more useful than the current 2) everywhere via new defaults?

@BridgeAR
Copy link
Member Author

BridgeAR commented Dec 29, 2017

@silverwind I do not see a big difference between 5 and unlimited. Most entries are not that deeply nested and if they are, you likely want to see everything. To prevent huge diffs, the max array entries option is way more efficient as this would otherwise be more difficult to handle.

About the complexity: I am fine with showing everything as a new default for console.* and this would remove the complexity again. But it would be a more significant change and I tried to minimize the breaking change.

For the repl it might be best to stay with the current default though. The reason is that some modules like fs have lots of nested elements and it would be be verbose otherwise.

@BridgeAR
Copy link
Member Author

@jasnell what do you think about removing the limit for console.* as well? I guess most people would actually profit from that.

@jasnell
Copy link
Member

jasnell commented Dec 29, 2017

Changing the default for console.* should be ok given that this is semver-major

Currently inspecting the BufferList can result a maximum call stack
size error. Adding a individual inspect function prevents this.
The current default is not ideal in most use cases. Therefore it is
changed to showing unlimited depth in case util.inspect is called
directly. The default is kept as before for console.log and similar.

Using console.dir will now show a depth of up to five and
console.assert / console.trace will show a unlimited depth.
Object.assign is currently very slow. Using Object.keys is much
faster in v8 6.3.
@BridgeAR
Copy link
Member Author

I changed the code to default to unlimited for the console functions as well.
To make that work I had to add a custom inspect function to the BufferList.

CITGM https://ci.nodejs.org/view/Node.js-citgm/job/citgm-smoker/1179/
CI https://ci.nodejs.org/job/node-test-pull-request/12350/

@@ -73,4 +74,8 @@ module.exports = class BufferList {
}
return ret;
}

[customInspectSymbol]() {
return `${this.constructor.name} { length: ${this.length} }`;
Copy link
Member

Choose a reason for hiding this comment

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

You could return { __proto__: Object.getPrototypeOf(this), length: this.length } which would also give coloring etc. for free.

Copy link
Member Author

Choose a reason for hiding this comment

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

Using __proto__ will actually result in a `call stack size exceeded error. I decided to call inspect directly instead to highlight the color in case it is needed.

@@ -317,7 +317,9 @@ Object.defineProperty(inspect, 'defaultOptions', {
if (options === null || typeof options !== 'object') {
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'options', 'Object');
}
Object.assign(inspectDefaultOptions, options);
Copy link
Member

Choose a reason for hiding this comment

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

  1. Do we actually care about the performance of inspection? I thought we didn’t.
  2. Same concern here as @lpinca. This is quite literally reinventing the wheel, and type checks for object are quite fast in modern V8.

@BridgeAR
Copy link
Member Author

BridgeAR commented Jan 2, 2018

@BridgeAR BridgeAR added author ready PRs that have at least one approval, no pending requests for changes, and a CI started. and removed author ready PRs that have at least one approval, no pending requests for changes, and a CI started. labels Jan 2, 2018
@BridgeAR BridgeAR requested a review from a team January 2, 2018 01:42
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Member

@targos targos left a comment

Choose a reason for hiding this comment

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

Can you please change the documentation of util.inspect (and add an entry to its history)?

@@ -73,4 +75,9 @@ module.exports = class BufferList {
}
return ret;
}

[customInspectSymbol]() {
Copy link
Member

Choose a reason for hiding this comment

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

I’d just use util.inspect.custom here, it saves people looking at this code one round-trip to another file

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

Since the default for depth is changed to `Infinity` it is logical
to change the %o default to the same as well.

Using %o with `util.format` will now always print the whole object.
@BridgeAR
Copy link
Member Author

BridgeAR commented Jan 3, 2018

I updated the documentation and added the history entry. I also changed the %o default of util.format to also use Infinity as default.

doc/api/util.md Outdated
* `depth` {number} Specifies the number visible nested Objects in an `object`.
This is useful to minimize the inspection output for large complicated
objects. To make it recurse indefinitely pass `null` or `Infinity`. Defaults
to `null`.
Copy link
Member

Choose a reason for hiding this comment

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

suggestion: Infinity instead of null to match the changelog?

BridgeAR added a commit to BridgeAR/node that referenced this pull request Sep 24, 2018
The current default is not ideal in most use cases. Therefore it is
changed to inspect objects to a maximum depth of 20 in case
util.inspect is called with it's defaults. The default is kept at 2
when using console.log() and similar in the repl.

PR-URL: nodejs#17907
Refs: nodejs#12693
BridgeAR added a commit to BridgeAR/node that referenced this pull request Sep 24, 2018
Since the default for depth is changed to `20` it is logical
to change the %o default as well. It will now always use the
default depth.

PR-URL: nodejs#17907
Refs: nodejs#12693
BridgeAR added a commit to BridgeAR/node that referenced this pull request Oct 2, 2018
The current default is not ideal in most use cases. Therefore it is
changed to inspect objects to a maximum depth of 20 in case
util.inspect is called with it's defaults. The default is kept at 2
when using console.log() and similar in the repl.

PR-URL: nodejs#17907
Refs: nodejs#12693

PR-URL: nodejs#22846
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Roman Reiss <me@silverwind.io>
BridgeAR added a commit to BridgeAR/node that referenced this pull request Oct 2, 2018
Since the default for depth is changed to `20` it is logical
to change the %o default as well. It will now always use the
default depth.

PR-URL: nodejs#17907
Refs: nodejs#12693

PR-URL: nodejs#22846
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Roman Reiss <me@silverwind.io>
@BridgeAR BridgeAR deleted the change-inspect-defaults branch April 1, 2019 23:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
console Issues and PRs related to the console subsystem. repl Issues and PRs related to the REPL subsystem. semver-major PRs that contain breaking changes and should be released in the next major version. util Issues and PRs related to the built-in util module.
Projects
None yet
Development

Successfully merging this pull request may close these issues.