svaarala / duktape

Duktape - embeddable Javascript engine with a focus on portability and compact footprint
MIT License
5.91k stars 513 forks source link

Profiling #526

Open supercranky opened 8 years ago

supercranky commented 8 years ago

Hello! Is there a feasible way to do profiling in Duktape? I'm thinking it would be useful to find good candidates of javascript functions/algorithms to reproduce in native code.

Love your work on Duktape!

svaarala commented 8 years ago

Unfortunately there's no profiling support at the moment. There is an internal interrupt mechanism which is used for script timeouts, debugger integration, etc, and that would be the basic mechanism to do sample-based profiling in the future.

supercranky commented 8 years ago

Good to know. Do you know of any other Javascript engine with similar characteristics that has an implemented profiler? Or maybe you could use some other strategy to find performance bottlenecks? I'm guessing there's really no point in doing the profiling in V8 or JavascriptCore

svaarala commented 8 years ago

The performance characteristics of JIT engines and interpreted engines are quite different so that profiling in V8 / JSC would only provide very rough understanding of where time is spent.

I'm not aware of other engines with profiling, but I'm not 100% sure because I don't work with them actively.

svaarala commented 8 years ago

Another approach for profiling which might be easier to implement would be logging function exit and entry timestamps to get rough function-level profiling information.

supercranky commented 8 years ago

Hmm, is that something that would be easy to implement at interpreter level? Getting total time spent per function would be great!

svaarala commented 8 years ago

A very quick and dirty approach would be to just debug log function entry and exit lines so that one could grep them and then compute the profiling results from that. A more refined version would use some configurable macro callback, or a native callback API, or something similar. The core change to log function entry/exit is much easier than deciding on the most appropriate exposed API which will then be maintained :)

supercranky commented 8 years ago

Ok, I'll just dive in there and do some testing! Thank you for taking the time!

svaarala commented 8 years ago

The calls are ultimately handled internally in these two functions:

For Ecmascript-to-Ecmascript calls, the decision to fallback to generic handling vs. using the Ecmascript-to-Ecmascript call setup route is made before this line: https://github.com/svaarala/duktape/blob/master/src/duk_js_call.c#L2432

These are the places where a function entry/exit based profiling mechanism would most likely hook into. Exposing a few macros to hook into these sites would be easy and not a big maintenance commitment (config macros are essentially free of overhead when not active).

supercranky commented 8 years ago

Great! Is there some super simple way of resolving a function name from idx_func? I'm guessing checking the "name" property of the function object would work?

svaarala commented 8 years ago

As an initial draft you could maybe just:

duk_get_prop_string(ctx, idx_func, "name");
your_func(duk_safe_to_string(ctx, -1));  /* ensures you get -some- name/string */
duk_pop(ctx);

As a better implementation one might want to avoid e.g. getter calls (in case .name is a getter); there are some internal functions which can avoid that but shouldn't be an issue for getting started.