Live data from Hacker News

Node.js in Flame Graphs

techblog.netflix.com

241–250 of 259 posts

Re: Node.js in Flame Graphs

#241
post #226

> I can’t imagine how we would have solved this problem without being able to sample Node.js stacks and visualize them with flame graphs. This has me scratching my head. The diagrams are pretty, maybe, but I can't read the process calls from them (the words are truncated because the graphs are too narrow). And I can't see, visually, which calls are repeated. They're stacked, not grouped, and the color palette is quit…

> The diagrams are pretty, maybe, but I can't read the process calls from them (the words are truncated because the graphs are too narrow).

Flame Graphs provide SVGs by default. You should be able to zoom if your broser supports it. The current version also supports "zooming" in to any frame in the stack, resetting that frame as the base of the display. Also WRT the base frames of 'node' et al its because Flame Graphs are a general use tool for stack visualization, it might be 'main' for a c program or the scheduler looking at a system.

> They're stacked, not grouped, and the color palette is quite narrow (color brewer might help here?).

Colors by default have no meaning and the palette is configurable. The current lib can also assign colors by instruction count/ipc and width by call count, if you have access to that.

> Sampling is only necessary if you've got -- really, truly, got -- big data (which Netflix probably does), but I don't think the author means 'sample' in a statistical sense.

It is sampling. Flame graphs re typically used with something like perf/dtrace/oprofile which dumps stacks at a couple hundred to thousand hertz. Actual call tracing is (typically) not feasible for large/prod stacks.

Re: Node.js in Flame Graphs

#242

The moneyquote: "We made incorrect assumptions about the Express.js API without digging further into its code base. As a result, our misuse of the Express.js API was the ultimate root cause of our performance issue." This situation is my biggest challenge with software these days. The advice to "just use FooMumbleAPI!" is rampant and yet the quality of the implemented APIs and the amount of review they have had varie…

I would say this is more of a mature software versus new software rather that open versus closed source . Node isn't even at version 1 yet.

Re: Node.js in Flame Graphs

#243

Earlier quoted context omitted.

I agree with you that the greatest strength of open source is that you can just go read the code and (optionally) fix it. Netflix did this and it got them past their crisis. I think you missed my point though, which was that there isn't any sort of fitness function being applied to open source. In the closed source environment that it 'price' (caveat walled gardens). By paying for the software customers "vote with th…

There totally is a fitness function for open-source. People who find that an open-source program creates more hassles than it solves don't use it. Folks who blog about their hassles induce other people not to use it. There are a number of open-source projects - web.py, Mongo, Angular, Ember - that I am actively avoiding because IMHO their benefits to me don't outweigh risks or previous hassles experienced. Much bette…

This mirrors my experience as well. Mature well known open source is usually excellent quality. Many of the more "modern" packages are often a lot more hassle.

Re: Node.js in Flame Graphs

#244
post #226

> I can’t imagine how we would have solved this problem without being able to sample Node.js stacks and visualize them with flame graphs. This has me scratching my head. The diagrams are pretty, maybe, but I can't read the process calls from them (the words are truncated because the graphs are too narrow). And I can't see, visually, which calls are repeated. They're stacked, not grouped, and the color palette is quit…

You're looking at a screenshot. The actual diagram isn't static. Hover over it and it will expand each box with all the info you need to see what was run, what called it, etc.

Re: Node.js in Flame Graphs

#245

this is why you stick to tried and true methods folks. this is such a typical node.js fanboy mentality. "reinventing the wheels is justified because asynchronous". or "i want this trendy way to do things just because everyone else is jumping on the bandwagon". Give me flask + uwsgi + nginx anyday.

In the end of the day Node.js is just a Reactor Pattern implementation in a form of bunch of scripts.

Re: Node.js in Flame Graphs

#246

Earlier quoted context omitted.

V8 literally compiles regexps to X86 machine code the first time they are executed. They are not compiled into an FSA that gets walked in the traditional sense. Hopefully that lowers your concern level.

Doesn't that mean that you have exponential worst-case complexity?

Absolutely! Even worse, you may get different results than the expected method (FSA compilation) would yield. Observe:

Javascript, executed in the console of a recent Chrome:

    > 'ab'.match(/a|ab/)  
    ["a"]
BSD Grep:

    > egrep 'a|ab' 

Re: Node.js in Flame Graphs

#247

Earlier quoted context omitted.

Regexps with backtracks are not regular languages (IIRC, right?), does that matter here?

That's right. Typical routing regexes will not use backreferences, so that's not really an issue here. However, most routes do have parameters implemented as capture groups (which, I believe, is also not technically a feature of regular expressions). One simple solution would be to use a big regex (the union of all the routes) to determine which route it is (in O(n) time), and then once you know the route, use anothe…

Just re-read this and realized it's unclear: when I said O(n) time, I meant linear in the length of the URL to be parsed. The point is that with this technique, it doesn't matter how many routes there are.

Re: Node.js in Flame Graphs

#248
post #181

Earlier quoted context omitted.

I'm not disagreeing and that's a perfectly valid reason to go for node for smaller projects or for prototyping. What many people fail to realise is that the "concurrency" model (it is solved by simply not having concurrency) isn't a magic bullet. It comes with large drawbacks. Not a lot of things are complicated because people like it that way. Some things are as complicated as they need to be to be used effectively.…

An example of basic concurrency I have great difficulty doing correctly in Java: n = 0; avg = 0; function twothings() { thing1(function(ret) { ++n; avg += (ret - avg)/n; }); thing2(function(ret) { ++n; avg += (ret - avg)/n; }); } I want to dispatch two I/O operations to run concurrently and have their completions modify some shared state in a serializable fashion, which can be read at any stage in the process and hav…

If you're having trouble with that, I suggest you take a look at CompletableFuture, or ExecutorCompletionService, or any other number of methods to do this in Java. Just like node has it's own lingo, so does Java, and once you learn it, things become real simple.

Re: Node.js in Flame Graphs

#249

Earlier quoted context omitted.

Doesn't that mean that you have exponential worst-case complexity?

Absolutely! Even worse, you may get different results than the expected method (FSA compilation) would yield. Observe: Javascript, executed in the console of a recent Chrome: > 'ab'.match(/a|ab/) ["a"] BSD Grep: > egrep 'a|ab'

Yow...

I was under the impression that all major regex engines used NFAs converted to DFAs lazily, with fallbacks to a slower engine for features that cannot (or cannot practically) be implemented using an NFA (unbounded backtracking, that sort of thing.)

What is the advantage to doing this?

Re: Node.js in Flame Graphs

#250
post #165

Earlier quoted context omitted.

This. I wrote something that did this a few years ago. It took n patterns (not regex, simpler) and turned them into one DFA state table with a function ptr stored for each final state. Then it had a tiny runtime. Never thought of using it for route tables however. Nice idea. Edit: I did consider rewriting the runtime as a forth style interpreter as well but the time never appeared.

How long does it take to build the DFA when a new route is added? That seems like the major time performance problem point if new routes are added often or regularly.

Worst case is absurd, yes. But most (all?) added routes that exhibit that behavior are routes that would exhibit that behavior when run as a regex (and hence converted into a DFA) on their own. (I.e. generally if you would shoot yourself in the foot with this method you've already shot yourself in the foot.)

Your worst case is O(nd + O(constructing the new route's DFA)), where "n" is the number of nodes in the previous DFA and "d" is the number of nodes in the DFA of the new route.

Note that constructing r's DFA can be done beforehand, and hence the actual time the router will be offline is only O(nd).

(Assuming a simple 2 DFA -> 1 NFA -> DFA merge. Your worst case is that every possible pair from the two, and singleton of the two is present in the final DFA, i.e. ({node from old, node from new} -> nd + {node from old} -> n + {node from new} -> d) -> O(nd + n + d) -> O(n*d). Note that this isn't the classic O(2^n) behavior, because we know that, due to the old DFA and new route DFA being DFAs, only one node in n and one node in d can be present at a time in the final stateset.

A better bet may be to use the classic "lazily-constructed DFA" approach. In other words, keep it as an NFA while only converting (sets of) nodes to DFA nodes when necessary. If you are worried about memory, you can even do this only for "hot" sections of the NFA, or only for those sections of the NFA that have the most performance gain for the number of nodes added.

Post reply on HN