Is it possible to choose the color for a given frame/function?
Hello,
I've been looking at https://github.com/jlfwong/speedscope/wiki/Importing-from-custom-sources. I was wondering if it would be possible to choose the color in which a frame is represented. For instance the color could represent which language/what kind of function it is, or whether the function is compiled or interpreted, etc.
- I looked at https://github.com/jlfwong/speedscope/blob/main/src/lib/file-format-spec.ts but could not see anything related to that.
- The collapsed stack format does not support it either, but the flamegraph.pl script has a
--colorpalette option. - The Google "Trace Event Format" seems to support a
cname, but that doesn't seem used by SpeedScope.
Is there a way to specify the color of frames/functions with speedscope?
Hi @eregon!
This isn't possible at the moment. Can you say a bit more about what your use-case is, and what kind of interface you'd like to have to support this?
https://github.com/brendangregg/FlameGraph can use different colors for native functions, functions running inside a java or javascript vm and kernel functions. This makes it easier to distinguish between user code, and code you have less influence on. The readme has the following example:
As for interface the native speedscope json format should have an option to directly define the kind of function I think. For imported profiles, speedscope could use the same guessing algorithm as flamegraph. For perf that would be the following logic: https://github.com/brendangregg/FlameGraph/blob/a258e78f17abdf2ce21c2515cfe8306a44774e2a/stackcollapse-perf.pl#L317-L334
Can you say a bit more about what your use-case is
My use-case is to use speedscope with GraalVM guest language profiling (i.e., for JS/Ruby/Python/LLVM/etc). So say a profile mixing Ruby, LLVM bitcode and potentially other languages as well.
We've found that being able to choose the color to be quite useful for:
- identifying the language at a glance (e.g., get an idea how much time is spent in LLVM bitcode vs in Ruby)
- identifying how much a function ran in JITed/compiled code. This is actually a ratio, the profiler is able to tell that method M ran X% compiled and the rest interpreted. The output below indicates 20.2% of the samples of that method were in compiled code (the rest in interpreter).
Name | Total Time | Opt % || Self Time | Opt % | Location
----------------------------------------------------------------------------------------------------------
yaml_parser_update_buffer | 186ms 0.2% | 21.5% || 178ms 0.2% | 20.2% | reader.c~142:0
Given these use cases, guessing based on the function name does not seem like it would work. Instead, the profiler has the precise information and we can use that. I also think something more abstract like some sort of category wouldn't work well, both because the compiled ratio is continuous, and because one might be able to choose more meaningful colors for languages than simply random colors.
and what kind of interface you'd like to have to support this?
For the speedscope format, I think the best way would be to have an optional color field in Frame (since this data does not change per frame, and if one needed 2 frames with different colors there is always the option to duplicate that Frame).
For the type, a HTML color string seems the most obvious (e.g., #8A2BE2).
It could also be an integer to maybe save some String creation when parsing the JSON, but it seems pointless since the browser would need the color string in the end anyway (AFAIK).
cc @aardvark179
For the speedscope format, I think the best way would be to have an optional color field in Frame (since this data does not change per frame, and if one needed 2 frames with different colors there is always the option to duplicate that Frame).
This approach sounds reasonable to me. I'm reluctant to provide a mechanism defining arbitrary color scheme functions or any guessing based on function names, but manual overrides of individual frame colors seems like it shouldn't be too bad to support.
One thing that could be tricky with this is that speedscope supports light & dark mode themes, and the foreground text color is different in each of them. How would you expect dark/light mode switching to work with custom colors?
it seems pointless since the browser would need the color string in the end anyway
speedscope does most of its rendering using WebGL, so I need to convert between formats anyway. But HTML color strings are nice in that they tend to be unambiguous, so that still sounds fine to me.
Before committing to this, I'd need to refresh my memory for how some of this code works, but I'm not philosophically opposed to this being part of speedscope.
One thing that could be tricky with this is that speedscope supports light & dark mode themes, and the foreground text color is different in each of them. How would you expect dark/light mode switching to work with custom colors?
Maybe the existing logic for that could apply fine? (still light grey text in dark mode) I'm not sure if function colors are changed between light & dark mode (seems like it), but probably the same transformation could also be done with custom colors to make it look nicer / similar to the current look. So conceptually I think it should work mostly fine to change the initial input color by the custom one if provided, and still apply whatever transformations on top for light & dark mode.
Implementation-wise, from a quick look it looks like we'd use the custom color if provided and colorForBucket() as currently otherwise.
the same transformation could also be done with custom colors to make it look nicer / similar to the current look.
The way the color scheme works right now isn't that there's a function that takes you from light theme to dark theme, so unfortunately this won't work.
The current color scheme works by taking a value between 0 and 1 and spitting out a color. So there is no mapping function from arbitrary light mode color -> dark mode equivalent, because the current light & dark color schemes don't contain all colors.