Skip to content

async-wrap: add provider id and object info cb - #1896

Closed
trevnorris wants to merge 1 commit into
nodejs:masterfrom
trevnorris:pass-provider-and-cb
Closed

async-wrap: add provider id and object info cb#1896
trevnorris wants to merge 1 commit into
nodejs:masterfrom
trevnorris:pass-provider-and-cb

Conversation

@trevnorris

Copy link
Copy Markdown
Contributor

Re-add the wrapper class id to AsyncWrap instances so they can be
tracked directly in a heapdump.

Previously the class id was given without setting the heap dump wrapper
class info provider. Causing a segfault when a heapdump was taken. This
has been added, and the label_ set to the given provider name so each
instance can be identified.

R=@bnoordhuis

For performance testing I ran the following:

varJSStream=process.binding('js_stream').JSStream;varITER=1e7;vart=process.hrtime();for(vari=0;i<ITER;i++)newJSStream();t=process.hrtime(t);console.log(((t[0]*1e9+t[1])/ITER).toFixed(1)+' ns/op');

It was the most direct way I found to instantiate a new AsyncWrap instance from JS. It shows no performance degradation with this patch applied.

Comment threadsrc/async-wrap.cc Outdated

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Here I'd prefer to unwrap the instance as the given provider type that's passed, but am coming up short on the necessary syntax.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

guess I could do a massive switch statement, but that feels wrong.

@mscdexmscdex added the c++ Issues and PRs that require attention from people who are familiar with C++. label Jun 4, 2015
Comment threadsrc/async-wrap.h 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.

I'm feeling a little bit un-easy about the magic Class Ids.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Is there a deterministic way to generate a class id? that's pretty much how it's done everywhere else in core.

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.

smalloc is the only other example I can find. We could maintain a central table for classIds. The danger that I am thinking about is if user-space modules need to use use classIds as well and happen to use the same value. It would be nice if one (i.e. user-space or core) could request a classId from the table. That way we can be sure that there won't be collisions.

I am only 'a little bit un-easy', and don't have objections to this PR landing as is.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good idea. Think that's definitely a PR to explore.

@trevnorris
trevnorrisforce-pushed the pass-provider-and-cb branch from 0a87ffd to e0268e3CompareJune 4, 2015 17:42
Comment threadsrc/node.js Outdated

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I'd prefer to just run SetWrapperClassInfoProvider() from node.cc, but then I'd have to migrate all the RetainedAsyncInfo logic as well. Thoughts on a better solution?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can't you export a function in src/async-wrap.cc and call that in src/node.cc?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Oop. Missed this comment. Sounds like a much better alternative.

@bnoordhuis

Copy link
Copy Markdown
Member

I see two issues with this PR.

  1. It reports the wrong size for instances, it's always sizeof(AsyncWrap). That's wrong in general and very wrong for variable length types like WriteWrap.
  2. It heap-allocates a new RetainedAsyncInfo for every instance and that:

2a. Wastes memory because most instances have a static layout and size.

2b. Probably slows down heap snapshots. RetainedAsyncInfo::IsEquivalent() only considers RetainedAsyncInfo instances equivalent when they point to the same AsyncWrap instance instead of instances of the same class. The heap snapshot generator has to do more work because of that although I don't know exactly how much more.

2a and 2b probably aren't that significant so long as there aren't too many AsyncWrap instances but 1 most definitely is.

@trevnorris

Copy link
Copy Markdown
ContributorAuthor

@bnoordhuis I should have labeled this as WIP. Knew before it was posted that the implementation was incomplete.

(1) was my biggest concern while writing this patch, and something I couldn't figure out on my own. Was hoping you'd have a suggestion about how to potentially get around it.

Wasn't aware of the issues pointed out in (2). Most of the implementation was pulled directly out of smalloc.cc, which originally came from your implementation in 6a128e0. I'll be more than happy to work on both those points if you think other issues in this PR can be worked out.

@bnoordhuis

Copy link
Copy Markdown
Member

I think the easiest solution to (1) is to add a virtual size_t self_size() const = 0; pure virtual method to AsyncWrap and have descendants implement that. For most, return sizeof(*this); will suffice.

Regarding (2), it would help to have static RetainedAsyncInfo instances for statically sized classes but that can be done as a future optimization.

@trevnorris
trevnorrisforce-pushed the pass-provider-and-cb branch 6 times, most recently from 67b3114 to 6965730CompareJune 8, 2015 23:00
@trevnorris

Copy link
Copy Markdown
ContributorAuthor

@bnoordhuis Thanks for the reviews. Finished fixing the last round.

While I've been wanting a means to do this (furthering use of AsyncWrap and all that), the patch became more invasive then I imaged it would be. If you can think of a more graceful implementation I'll redo this from scratch if necessary.

@trevnorris
trevnorrisforce-pushed the pass-provider-and-cb branch 2 times, most recently from 9c78909 to c47c024CompareJune 9, 2015 22:50
@trevnorris

Copy link
Copy Markdown
ContributorAuthor

@trevnorris

Copy link
Copy Markdown
ContributorAuthor

All test failures are the same:

not ok 105 - test-cluster-worker-wait-server-close.js

I doubt it's related to this PR, but don't know for sure.

@jbergstroem

Copy link
Copy Markdown
Member

@trevnorris the test seems to time out as well.

@trevnorris

Copy link
Copy Markdown
ContributorAuthor

@jbergstroem Thank for pointing that out.

@Olegas

Copy link
Copy Markdown
Contributor

I know this test. It's mine. It was kinda broken while #1400 is merged.

@trevnorris
trevnorrisforce-pushed the pass-provider-and-cb branch 3 times, most recently from 0890f6c to a511c2eCompareJune 10, 2015 23:14
@trevnorris

Copy link
Copy Markdown
ContributorAuthor

@trevnorris
trevnorrisforce-pushed the pass-provider-and-cb branch from a511c2e to 49d168bCompareJune 11, 2015 02:29
@trevnorris

Copy link
Copy Markdown
ContributorAuthor

And again. Something went strange w/ my force push last time.

https://jenkins-iojs.nodesource.com/job/iojs+any-pr+multi/799/

@trevnorris

Copy link
Copy Markdown
ContributorAuthor

CI completed. Same failures as before. None related to this patch.

@bnoordhuis if you're okay with the fixes, mind if I merge this?

Comment threadsrc/async-wrap.cc Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Magic constant.

@trevnorris
trevnorrisforce-pushed the pass-provider-and-cb branch from 49d168b to bb669c4CompareJune 15, 2015 21:40
@trevnorris

Copy link
Copy Markdown
ContributorAuthor

@bnoordhuis Thanks much for the additional review. All points have been addressed.

Re-add the wrapper class id to AsyncWrap instances so they can be
tracked directly in a heapdump.
Previously the class id was given without setting the heap dump wrapper
class info provider. Causing a segfault when a heapdump was taken. This
has been added, and the label_ set to the given provider name so each
instance can be identified.
The id will not be set of the passed object has no internal field count.
As the class pointer cannot be retrieved from the object.
In order to properly report the allocated size of each class, the new
pure virtual method self_size() has been introduces.
@trevnorris
trevnorrisforce-pushed the pass-provider-and-cb branch from bb669c4 to 5e792aaCompareJune 17, 2015 18:07
@trevnorris

Copy link
Copy Markdown
ContributorAuthor

@bnoordhuis

Copy link
Copy Markdown
Member

LGTM at a glance.

@trevnorris

Copy link
Copy Markdown
ContributorAuthor

Getting the following from centos5-32:

not ok 532 - test-process-argv-0.js
# argv=["/home/iojs/build/workspace/iojs+pr+linux/nodes/centos5-32/out/Release/iojs","/home/iojs/build/workspace/iojs+pr+linux/nodes/centos5-32/test/parallel/test-process-argv-0.js"]
# exec="/home/iojs/build/workspace/iojs+pr+linux/nodes/centos5-32/out/Release/iojs"
# CHILD: argv=["/home/iojs/build/workspace/iojs+pr+linux/nodes/centos5-32/out/Release/iojs","/home/iojs/build/workspace/iojs+pr+linux/nodes/centos5-32/test/parallel/test-process-argv-0.js","child"]
# # assert.js:89
# throw new assert.AssertionError({
# ^
# AssertionError: '' == '/home/iojs/build/workspace/iojs+pr+linux/nodes/centos5-32/out/Release/iojs'
# at ChildProcess.<anonymous> (/home/iojs/build/workspace/iojs+pr+linux/nodes/centos5-32/test/parallel/test-process-argv-0.js:26:12)
# at emitTwo (events.js:87:13)
# at ChildProcess.emit (events.js:172:7)
# at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)

Don't know how it could be related, so going to say that tests are looking good.

trevnorris added a commit that referenced this pull request Jun 17, 2015
Re-add the wrapper class id to AsyncWrap instances so they can be
tracked directly in a heapdump.
Previously the class id was given without setting the heap dump wrapper
class info provider. Causing a segfault when a heapdump was taken. This
has been added, and the label_ set to the given provider name so each
instance can be identified.
The id will not be set of the passed object has no internal field count.
As the class pointer cannot be retrieved from the object.
In order to properly report the allocated size of each class, the new
pure virtual method self_size() has been introduces.
PR-URL: #1896
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
@trevnorris

Copy link
Copy Markdown
ContributorAuthor

Landed in e56758a.

Thanks @bnoordhuis for the reviews.

@trevnorris
trevnorris deleted the pass-provider-and-cb branch June 17, 2015 19:04
@rvaggrvagg mentioned this pull request Jun 18, 2015
Sign up for freeto 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++.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@trevnorris@bnoordhuis@jbergstroem@Olegas@ofrobots@mscdex