Skip to content

uftrace for Erlang BEAM VM

Paran Lee edited this page Nov 14, 2023 · 6 revisions

This document is written by Yunseong Kim known as Paran Lee

Erlang is a programming language and runtime system for building massively scalable soft real-time systems with requirements on high availability.

OTP is a set of Erlang libraries, which consists of the Erlang runtime system, a number of ready-to-use components mainly written in Erlang, and a set of design principles for Erlang programs.

BEAM is Virtual Machine that run Erlang and Elixr Programming language.

  1. clone Erlang/OTP source code
git clone https://github.com/erlang/otp.git
  1. build with pg option Erlang/OTP
cd otp

export CFLAGS="-g3 -O0 -pg"
export CXXFLAGS="-g3 -O0 -pg"

./configure

time make -j8 | tee make-build.log
time ERL_TOP=$(pwd) make -j8 -C erts/emulator debug gcov asan gprof 2>&1 | tee erts_emulator-build.log
time ERL_TOP=$(pwd) make -j8 -C erts/lib_src debug gcov asan gprof 2>&1 | tee erts_lib_src-build.log
time ERL_TOP=$(pwd) make -j8 -C lib/crypto/c_src debug gcov asan gprof 2>&1 | tee lib_crypto_c_src-build.log
  1. Do uftrace!

escript

Test code factorial.erl

 otp$ cat factorial.erl 
#!/usr/bin/env escript
%% -*- erlang -*-
%%! -sname factorial -mnesia debug verbose
main([String]) ->
    try
        N = list_to_integer(String),
        F = fac(N),
        io:format("factorial ~w = ~w\n", [N,F])
    catch
        _:_ ->
            usage()
    end;
main(_) ->
    usage().

usage() ->
    io:format("usage: factorial integer\n"),
    halt(1).

fac(0) -> 1;
fac(N) -> N * fac(N-1).

Trace the factorial erlang program.

 otp$ $HOME/uftrace/uftrace record --libmcount-path=$HOME/uftrace bin/escript factorial.erl 3
mcount: /home/kim/uftrace/libmcount/misc.c:85:uftrace_send_message
 ERROR: writing shmem name to pipe: Bad file descriptor
erl_child_setup closed

Crash dump is being written to: erl_crash.dump...done

 otp$ uftrace replay
# DURATION     TID     FUNCTION
            [ 24096] | main() {
            [ 24096] |   emalloc() {
   1.900 us [ 24096] |     malloc();
   2.700 us [ 24096] |   } /* emalloc */
   0.100 us [ 24096] |   strlen();
   1.300 us [ 24096] |   strcmp();
   0.300 us [ 24096] |   strncpy();
            [ 24096] |   get_env() {
   0.200 us [ 24096] |     getenv();
   0.300 us [ 24096] |   } /* get_env */
            [ 24096] |   get_default_emulator() {

erl execute oneline code by beam.smp

 otp$ export BINDIR=/home/kim/otp/bin/x86_64-pc-linux-gnu && $HOME/uftrace/uftrace record --libmcount-path=$HOME/uftrace /home/kim/otp/bin/x86_64-pc-linux-gnu/beam.smp -- -root /home/kim/otp -bindir /home/kim/otp/bin/x86_64-pc-linux-gnu -progname erl -- -home /home/kim -- -noshell -eval 'io:fwrite("Hello, World!"), init:stop().'
mcount: /home/kim/uftrace/libmcount/misc.c:85:uftrace_send_message
 ERROR: writing shmem name to pipe: Bad file descriptor
erl_child_setup closed

Crash dump is being written to: erl_crash.dump...done

 otp$ $HOME/uftrace/uftrace replay
# DURATION     TID     FUNCTION
            [ 25214] | _GLOBAL__sub_I_BeamGlobalAssembler::emitPtrs() {
            [ 25214] |   __static_initialization_and_destruction_0() {
   0.400 us [ 25214] |     std::allocator::allocator();
            [ 25214] |     std::map::map() {
   0.500 us [ 25214] |       std::allocator::allocator();
            [ 25214] |       std::_Rb_tree::_Rb_tree() {
   0.300 us [ 25214] |         std::allocator::allocator();
            [ 25214] |         std::_Rb_tree::_Rb_tree_impl::_Rb_tree_impl() {
   0.100 us [ 25214] |           std::move();
   0.800 us [ 25214] |           std::allocator::allocator();
   0.100 us [ 25214] |           std::_Rb_tree_key_compare::_Rb_tree_key_compare();
            [ 25214] |           std::_Rb_tree_header::_Rb_tree_header() {
   0.100 us [ 25214] |             std::_Rb_tree_header::_M_reset();
   0.300 us [ 25214] |           } /* std::_Rb_tree_header::_Rb_tree_header */
   1.900 us [ 25214] |         } /* std::_Rb_tree::_Rb_tree_impl::_Rb_tree_impl */
            [ 25214] |         std::allocator::~allocator() {
   0.100 us [ 25214] |           __gnu_cxx::new_allocator::~new_allocator();
Clone this wiki locally