Thanks for the link to that video, I'll give it a look. Based on your suggestion I'll try doing a custom build of Chromium and see if the disassembly will let me make sense of things.
The reason this is a real problem for me (and why I find the lack of documentation for this stuff in chromium frustrating) is that I'm machine-translating code from other languages to JS - hand-editing it to make it faster is something I can do for code I'm writing myself, but I can't do it in a compiler. The current nature of the performance feedback from V8 makes it more or less a black box and this is worsened by the fact that a large amount of the documentation I've found out there that claims to describe V8 performance characteristics is either wrong or outdated. When you profile an application in V8 and the web inspector says you're spending 50% of your time in a simple function, your only choice is to dig deeper to try and understand why that function is slow. You could solve this by offering line-level profiling data in your profiler, but I think that's probably a ton of work, so I'm not asking for that. ;) To provide one example: I did some spelunking around with --trace-deopt and --trace-bailouts and found that in my codebase, basically any use of the 'arguments' object - even just checking 'arguments.length' - causes the entire function to be deoptimized. Of course, there isn't a ton of documentation here, but http://s3.mrale.ph/nodecamp.eu/#57 along with other sources claim that this is not the case. So, either something creepy is happening in my test cases - more verbose feedback from V8 here, or concrete docs from the devs themselves would help - or the information being given to the public is wrong. Non-v8/non-chrome devs saying false things about V8 performance isn't your fault, but it wouldn't hurt to try and prevent that by publishing good information in textual form on the web. I hope I'm not giving the impression that I think V8 is the only problem here either; JS performance in general is a labyrinth. Based on my experiences however, the best way to get info about V8 performance tuning is to talk to a Chromium dev directly or hunt down YouTube videos of hour long presentations. This is pretty suboptimal for a developer who's trying to tackle a performance issue in the short term - Google is surprisingly bad at finding either of those two info sources when you dig around or search for diagnostic messages. I've personally been documenting everything concrete I learn about this stuff on my wiki, but once I stop doing this day-to-day, all that information will get outdated and mislead future developers. I think that sucks, and the only good solution is for JS runtime devs to provide concrete information on performance pitfalls and such in an easily found location and keep it somewhat up to date. I don't think you guys necessarily need to make --trace-deopt or --trace-bailout super user friendly, but if you don't, there needs to be some basic guidance out there for developers so that JS flags aren't their only option for understanding Chrome performance. Thanks for the info about c1visualizer - I bet the memory limit was probably responsible for the flakiness and if I fiddle with JVM parameters it might work. I'll give it another try later on. -kg On Tue, Jul 17, 2012 at 3:32 PM, Jakob Kummerow <[email protected]> wrote: > Seems like you're finding out the hard way what a complicated beast a modern > JS engine is ;-) > > --trace-deopt is certainly usable; but it is not geared towards ease-of-use > for JavaScript developers, that's for sure. > > Helpful flags are --print-opt-code and --code-comments. Those two together > will print the disassembled code for *optimized* functions, interleaved with > some comments, such as the IDs of the HIR instructions that generated the > code (which is what the "@36" in your example refers to), and the > deoptimization IDs ("bailout #7" in your example). And yes, there can be a > lot of disassembled code that gets printed when you feed a lot of JavaScript > code to V8 -- redirecting output to a file and opening that with an editor > makes this easier to manage. > > Since disassembly is involved, --print-opt-code only works when V8 has been > built with disassembler support. That's the case in a debug mode build, or > in release mode when you specify GYPFLAGS="-Dv8_enable_disassembler=1" (when > you build d8 with GYP/make, we have a convenience option for that: "make > disassembler=on ia32.release"). If you build your own Chromium anyway, you > can also change the flag's default value in src/v8/build/common.gypi, if you > find that easier than setting an environment variable. > > Due to the optimizations that the optimizing compiler does, there is no > mapping from assembly instructions (or deopt points) to line numbers. I'm > not sure if and with how much effort it'd be possible to hack up support for > that. I agree that it would be great if Chrome's dev tools could show you > where deopts happened, and why... > > c1visualizer is still state of the art to visualize what the optimizing > compiler does. Yes, it's a somewhat sorry state of things, but it can be > very helpful. Probably more helpful for debugging the compiler than for > debugging JavaScript, though. Upping the max memory helps a lot when loading > large hydrogen.cfg dumps. > > There aren't all that many reasons for deopts, and it's relatively easy to > learn which JS constructs can cause a deopt at all: mainly stuff that hasn't > happened earlier, e.g. accessing a property of an object with a new type, or > a double value suddenly being undefined, or code after a long-running loop > that's never been executed before, or an array access out of bounds that was > within bounds earlier, and so on. So with some experience, and assuming > you're not running into bugs/deficiencies of V8, staring at assembly code > won't even be necessary. Also, if you find that by refactoring your function > (e.g. splitting it into two smaller functions) you can prevent the deopt, > that's not really a problem, is it? It's kind of the solution you were > looking for in the first place, right? > [Btw, there's a pretty recent video of a talk that explains some of this, > and mentions some common pitfalls to avoid: > http://www.youtube.com/watch?v=UJPdhx5zTaw ] > > Ranting about flags or their output being cryptic may help you let off some > steam, but beyond that doesn't get you anywhere. V8's command-line flags let > you peek at V8's inner workings, and making sense of their output requires > some understanding of these internals. Nobody ever claimed anything else. > > > On Tue, Jul 17, 2012 at 8:34 PM, Kevin Gadd <[email protected]> wrote: >> >> I've spent the last couple hours trying to actually get anything useful >> out of --trace-deopt. Unfortunately, I've had no success. I'm primarily >> going off the information from >> http://floitsch.blogspot.com/2012/03/optimizing-for-v8-inlining.html, as >> it's the only detailed info I've found on the internet about --trace-deopt. >> >> From what I can tell, the only way to use this feature seems to be in a >> debug build of d8, and to map the offsets (I think they're offsets? Unable >> to find information on this) in the deopt spew back to the generated >> assembly from the JIT, using the --print-code option. I.E.: >> >> **** DEOPT: MouseCursor_get_ClientBoundsWidth at bailout #7, address 0x0, >> frame size 12 >> ;;; @36: deoptimize. >> >> In this spew I *think* @36 refers to instruction #36 in the generated IR >> from the JIT? It's unclear whether this is the high level IR or the low >> level IR (hydrogen.cfg, when you can actually get c1visualizer to load it, >> claims there are two kinds of IR - more on that later). >> >> So, right off the bat, this seems less than helpful - --print-code >> generates an absolutely titanic dump of all sorts of data and none of it is >> correlated - nothing in the output ASM maps it back to the source JS, and >> the IR (the IR that shows up in hydrogen.cfg) doesn't even seem to be there. >> It's unclear what the @36 in this case would actually point to, or how once >> I had located 36 I would map it back to a defect in my original source >> JavaScript or even to a particular operation in the IR. Mapping my >> JavaScript to V8's IR seems like something I can manage if necessary - most >> of the opcodes are KIND OF self explanatory if you spend forever >> understanding V8. But mapping the raw JIT assembly back to JS is just plain >> nuts - there's way too much going on there to even understand what a given >> deoptimization means if this is the only information I have. >> >> Really, all I need here is a rough mapping that tells me what part of a >> function is triggering a deoptimization. If V8 can't give me a reason (this >> seems to almost universally be the case), then fine, I'll just figure it out >> with brute force - but without knowing roughly what part of the function is >> responsible it's impossible to do any real debugging or optimization here >> (trying to binary search the function manually won't work, because changing >> the size and structure of the function will change whether it deoptimizes >> and where it deoptimizes). >> >> http://floitsch.blogspot.com/2012/03/optimizing-for-v8-hydrogen.html >> suggests that it's possible to get at the IR using some debug flags, and >> when I tried them out they indeed generate an enormous file named >> hydrogen.cfg. Unfortunately, the tool the post suggests using - c1visualizer >> - is either broken or does not support the version of the .cfg format Chrome >> now spits out, because it fails to load almost every meaningfully large .cfg >> file I've ever managed to get. When it does successfully load one, most of >> the functions I care about are missing, which suggests that the file is >> incomplete or their parser stopped early. The file is large and noisy enough >> that I don't think I'd be able to make sense of it by hand without a >> visualizer tool. Is there a working replacement for c1visualizer that the >> Chrome team uses now? I searched for one but couldn't find anything. Do I >> have to write my own visualizer? >> >> Even if the enormous spew of raw assembly from d8 with --print-code and >> --trace-deopt were usable (at present it doesn't seem usable without more >> complete information), it doesn't feel like enough to solve real performance >> issues. I'm looking at deoptimizations right now that only seem to occur >> when actually running an application in Chrome (i.e. interacting with APIs >> like WebGL and Canvas), which is where I actually care about performance - I >> can't simply reduce all of these deoptimized functions into test cases >> because they don't work without access to the rest of their dependencies. >> >> It seems like maybe if I built a debug version of Chromium myself, I'd be >> able to pass *it* --print-code, but then I'd be missing codecs like MP3, >> and, I'd still have to deal with the enormous spew of data and raw assembly >> there. >> >> All I really want is line numbers. Is this possible? Could I possibly get >> it by hand-patching v8 in the right place and building my own Chromium? >> >> Also, I could rant about how cryptic --trace-bailout is, but that feature >> at least seems to work and provide actionable data (if you're willing to >> grep through the v8 source code and try and understand what the terminology >> means and set breakpoints to follow consequence chains and understand *why* >> a particular bailout actually occurred). Really right now the >> deoptimizations are my biggest concern because hundreds of them are >> happening every second versus a very small number of bailouts. >> >> Thanks, >> -kg > > > -- > v8-users mailing list > [email protected] > http://groups.google.com/group/v8-users -- -kg -- v8-users mailing list [email protected] http://groups.google.com/group/v8-users
