parca-dev / parca

Continuous profiling for analysis of CPU and memory usage, down to the line number and throughout time. Saving infrastructure cost, improving performance, and increasing reliability.
https://parca.dev/
Apache License 2.0
3.95k stars 211 forks source link

Elixir Support #2392

Open dogukanzorlu opened 1 year ago

dogukanzorlu commented 1 year ago

Hi Parca peoples,

for Parca to provide Elixir support, I developed a library that imitates net/http/pprof in golang and generates meaningful pprof profile data from internal erlang library :fprof.

Many explanations you need are available in the documentation. But still, I will write the same ones and the additions here.

Aim The observation and profiling culture of erlang and elixir is different from other languages. Elixir/Erlang runs on a virtual machine (a.k.a beam) and each block of code represents a process. Erlang provides many tools internally for monitoring abstracted processes and processes dependent functions. This library produces as meaningful pprof output as possible using the built-in Erlang profiling tools. Thus, it tries to spread the Erlang/Elixir observability with pprof-based ad-hoc profiling tools.

A few important things

Screenshot from 2023-01-10 12-20-38

source: github Thanks! @kakkoyun @brancz

kakkoyun commented 1 year ago

xref https://github.com/parca-dev/parca-agent/issues/145

brancz commented 1 year ago

Very cool! I'm curious, what do the numbers before the closing curly brackets mean are they parameters? For a 5 seconds profile 1.1k samples seems like a lot, what's the sampling frequency?

dogukanzorlu commented 1 year ago

{ModuleName, Function, Arity} so its mean for example Erlang.garbage_collect(arg1, arg2) -> {:erlang, :garbage_collect, 2}. actually fprof is not simple call stack sampling, fprof traces the entire process on the beam and the invoked functions that depend on the processes. therefore most of time sampling so huge. Unfortunately, I couldn't find any content about frequency in fprof and its source code. @brancz

brancz commented 1 year ago

{ModuleName, Function, Arity} so its mean for example Erlang.garbage_collect(arg1, arg2) -> {:erlang, :garbage_collect, 2}.

Got it! Thanks for the explanation!

actually fprof is not simple call stack sampling, fprof traces the entire process on the beam and the invoked functions that depend on the processes. therefore most of time sampling so huge. Unfortunately, I couldn't find any content about frequency in fprof and its source code.

Judging by the docs I would be careful with using this continuously, it seems like fprof and eprof are meant as one-off tools (even the docs claim they add significant overhead). Only cprof seems to be sampling and <10% impact (still rather large for continuous profiling purposes).

I would suggest doing the CPU profiling with the Parca Agent and using the ERL_FLAGS="+S 1 +JPperf true" flag on the erlang/elixir application. This should give great visibility at very low overhead.

Anything memory-related, especially heap is something that would make a ton of sense to be in a library like you created! In any case, nice work looking forward to seeing more!

dogukanzorlu commented 1 year ago

Exactly you are right about continuously. But considering that there is no pprof in elixir or erlang, it's not bad for a start. I will also produce pprof for memory and process. I am also working on perf maps related VM. In any case, thank you for your comments. @brancz

brancz commented 1 year ago

Thank you so much for this work, the community needs this type of engagement!