Re: [v8-users] V8 JavaScript Stack Trace API

684 views
Skip to first unread message

Erik Corry

unread,
Jun 29, 2010, 3:46:59 PM6/29/10
to nod...@googlegroups.com
This is probably of interest to Node users too:

Den 29. jun. 2010 08.49 skrev Søren Gjesse <sgj...@chromium.org>:
There has been a JavaScript stack trace API in V8 for some time now, but it have not been well documented. However this has now been fixed and the nice documentation by christian.plesner.hansen can be found at http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi.

There is also a C++ counterpart for which the documentation is in the C++ header file. Look for class StackTrace and friends in http://code.google.com/p/v8/source/browse/branches/bleeding_edge/include/v8.h.

Regards,
Søren

--
v8-users mailing list
v8-u...@googlegroups.com
http://groups.google.com/group/v8-users



--
Erik Corry, Software Engineer
Google Denmark ApS.  CVR nr. 28 86 69 84
c/o Philip & Partners, 7 Vognmagergade, P.O. Box 2227, DK-1018 Copenhagen K, Denmark.

Felix Geisendörfer

unread,
Jun 29, 2010, 6:54:05 PM6/29/10
to nodejs
I don't see this in the docs, but would it be possible to invoke a V8
function with a pre-populated stack trace?

Right now it's very hard to debug event loop events. To illustrate:

http://gist.github.com/457949

As you can see the stack trace is lost on each event loop tick. I
wonder how/if we could fix this. Ryan: Any ideas?

--fg

On Jun 29, 9:46 pm, Erik Corry <erik.co...@gmail.com> wrote:
> This is probably of interest to Node users too:
>
> Den 29. jun. 2010 08.49 skrev Søren Gjesse <sgje...@chromium.org>:
>
>
>
>
>
> > There has been a JavaScript stack trace API in V8 for some time now, but it
> > have not been well documented. However this has now been fixed and the nice
> > documentation by christian.plesner.hansen can be found at
> >http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi.
>
> > There is also a C++ counterpart for which the documentation is in the C++
> > header file. Look for class StackTrace and friends in
> >http://code.google.com/p/v8/source/browse/branches/bleeding_edge/incl...
> > .

Timothy Caswell

unread,
Jun 29, 2010, 6:58:20 PM6/29/10
to nod...@googlegroups.com
So somehow add the stack trace for when the callback was set to when the callback is called? Sounds interesting. You'd have to hook into everything that sets up events.

> --
> You received this message because you are subscribed to the Google Groups "nodejs" group.
> To post to this group, send email to nod...@googlegroups.com.
> To unsubscribe from this group, send email to nodejs+un...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/nodejs?hl=en.
>

r...@tinyclouds.org

unread,
Jun 29, 2010, 8:47:23 PM6/29/10
to nod...@googlegroups.com
2010/6/29 Felix Geisendörfer <fe...@debuggable.com>:

> I don't see this in the docs, but would it be possible to invoke a V8
> function with a pre-populated stack trace?
>
> Right now it's very hard to debug event loop events. To illustrate:
>
> http://gist.github.com/457949
>
> As you can see the stack trace is lost on each event loop tick. I
> wonder how/if we could fix this. Ryan: Any ideas?

Yes. Here is my plan:

I will split the EventEmitter class/concept into two things. One will
be C++ a base class (deriving from ObjectWrap) for all "watchers" (a
libev term), call it (for now) a Hard Event Emitter. The other will be
JS only for now call it a Soft Event Emitter.

Hard Event Emitters get callbacks directly off the event loop (or at
least almost directly off the event loop - maybe via libpq) they make
the first call into JS. Hard Emitters are where "the buck stops" when
an exception is thrown in somewhere in the stack - Soft Emitters will
allow the exception to propagate up, but Hard Emitters must deal with
it - there is no where eles to go. Dealing with it means either

1) Calling the 'uncaughtException' event
or
2) Exiting the process and printing the stack trace associated with
the exception.

What we can do is every time a Hard Emitter is created, record the
stack and store it in the Hard Emitter. Then if that Emitter ever hits
an exception, it will print the stack associated with the exception
plus the stack it recorded when it was created.

This will give a lot more context into where errors are created.

You could take it a step further: When Hard Emitters are created, in
addition to recording the stack they could record a link to the Hard
Emitter whose callback they are currently in. This would allow you to
walk backwards arbitrarily far to see where an exception originated.

Recording a link to another Hard Emitter doesn't cost much - it's
likely this can be done even in very busy servers. However it's
unknown how expensive recording a stack trace is (specifically
v8::StackTrace::CurrentStackTrace(),
http://github.com/ry/node/blob/242161bef2e3631d315f8da8a62c088bdc100c87/deps/v8/include/v8.h#L778-787)
- likely slow enough that it will show up in benchmarks if we're doing
it for every single Hard Emitter construction. Thus we should plan to
have this be an optional feature, enabled by a command line flag
(--debug enables it?).

Soft Emitters will be just sugar. Actually they will be exactly what
exists in lib/events.js currently:

http://github.com/ry/node/blob/242161bef2e3631d315f8da8a62c088bdc100c87/lib/events.js

Example: in a TCP socket, the Hard Emitter would the be the IOWatcher
which emits a "readable" event for the associated file descriptor. The
net.js code does some stuff (reads data from the fd into a Buffer) and
eventually emits a "data" event from it's user-facing Soft Emitter
interface.


Two random notes about this refactor:


1) It lends to a good infrastructure for sticking in dtrace probes. We
can do probes on Hard Emitters completely in C++.

2) (I'm not suggesting this API, just pointing out that this refactor
will allow for such things.) There is also the possibly of having an
interface for recovering from errors. Imagine:

t = setTimeout(function () {
throw new Error('xxx');
}, 1000);

t.onException = function (e) { /* ... */ };

Ryan

Felix Geisendörfer

unread,
Jun 30, 2010, 3:41:15 AM6/30/10
to nodejs
This sounds fantastic Ryan!

If it ends up becoming problematic for our hello world olympics, I'm
fine with a flag for either disabling/enabling it. (Enabled by default
would be preferable so).

--fg
> v8::StackTrace::CurrentStackTrace(),http://github.com/ry/node/blob/242161bef2e3631d315f8da8a62c088bdc100c...)
> - likely slow enough that it will show up in benchmarks if we're doing
> it for every single Hard Emitter construction. Thus we should plan to
> have this be an optional feature, enabled by a command line flag
> (--debug enables it?).
>
> Soft Emitters will be just sugar. Actually they will be exactly what
> exists in lib/events.js currently:
>
> http://github.com/ry/node/blob/242161bef2e3631d315f8da8a62c088bdc100c...

Isaac Schlueter

unread,
Jun 30, 2010, 2:07:48 PM6/30/10
to nod...@googlegroups.com
I also support this plan.

However, if it causes any relevant performance impact (which I suspect
it will), I think it should be disabled by default, unless you
./configure --debug, since it's an advanced debugging option.

It might be nice to have a ./configure --with-event-trace so that you
could enable this feature without adding the overhead of the other
debug() function calls.

--i

2010/6/30 Felix Geisendörfer <fe...@debuggable.com>:

Felix Geisendörfer

unread,
Jun 30, 2010, 2:27:54 PM6/30/10
to nodejs
> However, if it causes any relevant performance impact (which I suspect
> it will), I think it should be disabled by default, unless you
> ./configure --debug, since it's an advanced debugging option.

I may have misunderstood Ryan, but I was thinking about a run-time
switch you directly pass to the node binary (debug or not).

--fg

r...@tinyclouds.org

unread,
Jun 30, 2010, 3:06:29 PM6/30/10
to nod...@googlegroups.com
2010/6/30 Felix Geisendörfer <fe...@debuggable.com>:

>> However, if it causes any relevant performance impact (which I suspect
>> it will), I think it should be disabled by default, unless you
>> ./configure --debug, since it's an advanced debugging option.
>
> I may have misunderstood Ryan, but I was thinking about a run-time
> switch you directly pass to the node binary (debug or not).

Yeah.

Joe Developer

unread,
Jun 30, 2010, 4:48:56 PM6/30/10
to nod...@googlegroups.com
It strikes me as it almost doesn't matter then:

Disabled by default in order to aid performance +1
Require a debug build to acquire it +1

The use case for having it 'built-in' would be to catch 'rare' occurences in a production environment, if you need to restart your app with a new switch, why not just restart it with a debug build?

Admittedly I am not clear on how heavy the switch implementation would be or how often it would be evaluated, but I would wager that it all adds up. 

That said, I would be just as happy with a ./configure --for-pure-speed

Isaac Schlueter

unread,
Jun 30, 2010, 4:53:23 PM6/30/10
to nod...@googlegroups.com
> ./configure --for-pure-speed

The "--for-pure-speed" option should be implied by the fact that
you're using NodeJS in the first place.

--i

Joe Developer

unread,
Jun 30, 2010, 5:03:19 PM6/30/10
to nod...@googlegroups.com
On Thu, Jul 1, 2010 at 3:53 AM, Isaac Schlueter <i...@izs.me> wrote:
> ./configure --for-pure-speed

The "--for-pure-speed" option should be implied by the fact that
you're using NodeJS in the first place.

Of course :) But there is no sense in not making it as fast as possible - I certainly didn't mean to imply that node.js is not fast - merely that 'fast enough' is a mindset to be avoided. ;)
Reply all
Reply to author
Forward
0 new messages