Profiling of cells?

I’m working on a program that does a few heavy computations and lots of rendering, and I want to track which cells are making it slow.

It would be super cool to be able to read the time spent by the system in each cell, and the number of times it’s been called / has yielded.

Currently what I’m doing is having a cell with:
instrumentation = ({})

then in all other interesting cells,

const start = performance.now();

…computes result…

instrumentation.delaunay = performance.now() - start;

return result;

Any idea that could make this leaner? I also wonder if a variant of this could not be a native feature.

4 Likes

That’s a very interesting suggestion.

My main instinct is that it’s going to be very hard for us to add anything more useful than what your browser inspector already provides. I assume that you’ve already tried your browser performance profiler on your notebook? Even running in the sub-frame, notebooks are pretty easy to profile, use the debugger, and so on.

For example, running it on my old earthquakes notebook shows me that I’m allocating a lot of JS objects that I shouldn’t be, if I want to avoid GC pauses:

Is there a reason why the profiler wouldn’t tell you which cell is taking up most of the time in your notebook?

Is there a documentation of where to find the objects managed by Observable in the browser developpers tools? For example: how to print the value of a cell in the console?

@severo

The Observable runtime doesn’t expose the graph of cells as global variables, but you can certainly log the value of any cell to the console from within a notebook. Because of the reactive runtime, it will even re-log the cells value whenever it changes:

console.log(cell)
1 Like

Thanks. I already use that way, but I wondered if it would be possible to inspect any of the variables directly from the console, without console.log().
What is the reason to hide the variables?

Probably the reason is my own limitations with the profiler. On your earthquakes page, for example, I don’t know where to read the names of the functions involved (those that have this red-ear marker). Everything seems hidden in “observable workers”. I’ll dig more.

Jeremy’s picture might not be the easiest screencap to see what you are looking for. Here’s the Chrome dev tools timeline with a “bottom up” tree of one animation frame.

Part of the difficulty may be that you get a mix of anonymous functions and minified names, so it’s a bit hard to guess what the functions are actually about. If you loaded an unminified version of D3 it would probably be clearer

Ha! so it looks like something is missing from my Chrome devtools…

Firefox works, I’ll be fine :slight_smile:

@Fil — I think you’re right about this. I too have trouble peering inside of the inspector to see what’s going on within the “micro task” promise callbacks that serve as the bodies of your cells being evaluated.

For example, in Chrome, I can’t see within the “Run Microtasks” and “Animation Frame Fired” activity to see the names of the function being called, that take up most of the run time:

And in Firefox, although you can see the functions reported in the flame graph:

… you can’t navigate to their source from there.

The call tree is a little more helpful at telling you where the expensive calls are coming from — but still fundamentally points back at an eval() in minified source code:

We need to figure out a better approach…

1 Like

Okay weird, now I can’t get back to my previous screenshot either.

Maybe Chrome updated itself between then and now, and the new version has a less useful profiler? I’m not quite sure what happened, but I don’t have time to figure it out right now…

For what it’s worth, a while back I wrote an FPS meter and toyed around with the various cell update methods: https://beta.observablehq.com/d/8bea3f94176f0330

1 Like

for fps I’m using exponential decay, makes me feel like an atomic scientist

3 Likes