msacc(3)

๐Ÿ“ฆ
version 29.0.6 ยท 3 versions
, in ubuntu stonking

โœจ msacc ๐Ÿ’… the manual, but make it a whole vibe โœจ

okay so bestie, welcome to msacc, straight outta section 3 of the Erlang manual. It's the Erlang Module Definition we're talking about, and it's giving "I make microstate accounting make sense" energy. Let's get into it. ๐Ÿซถ


๐ŸŒธ NAME ๐ŸŒธ

msacc โ€” convenience functions for microstate accounting. periodt. ๐Ÿ’–


๐Ÿฆ‹ DESCRIPTION ๐Ÿฆ‹

So this module is literally a little care package of convenience functions for analyzing microstate accounting data. If you wanna know how to use the basic API and what all the different states actually mean, go peek at erlang:statistics(microstate_accounting). iykyk. โœจ

๐ŸŽ€ Basic Scenario (a whole lil demo) ๐ŸŽ€

Look at her go:

1> msacc:start(1000).
ok
2> msacc:print().
Average thread real-time    : 1000513 us
Accumulated system run-time :    2213 us
Average scheduler run-time  :    1076 us

        Thread      aux check_io emulator       gc    other     port    sleep

Stats per thread:
     async( 0)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%  100.00%
     async( 1)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%  100.00%
       aux( 1)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%   99.99%
 scheduler( 1)    0.00%    0.03%    0.13%    0.00%    0.01%    0.00%   99.82%
 scheduler( 2)    0.00%    0.00%    0.00%    0.00%    0.03%    0.00%   99.97%

Stats per type:
         async    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%  100.00%
           aux    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%   99.99%
     scheduler    0.00%    0.02%    0.06%    0.00%    0.02%    0.00%   99.89%
ok

The first command โ€” that's msacc:start(1000) โ€” turns on microstate accounting for 1000 milliseconds, no cap. Wanna know more? Check start/0, stop/0, reset/0, and start/1. The second command prints out all the stats it collected during that window. ๐Ÿ“

First up: three general statistics get printed. iconic.

  • Average real-time โ€” the average time spent collecting data in the threads. This should be close to the time that data was actually collected. ๐Ÿ‘‘
  • System run-time โ€” the total run-time of all threads in the system. This is exactly what you get if you call msacc:stats(total_runtime,Stats). ๐Ÿ’œ
  • Average scheduler run-time โ€” the average run-time for the schedulers, aka the average amount of time the schedulers did not sleep. ๐Ÿ˜ดโžก๏ธ๐Ÿ”ฅ

Then, one column per state gets printed, showing the percentage of time that thread spent in that state out of its own real-time. Cute, right? And after the thread-specific time, the accumulated time for each type of thread gets printed in a similar format. ๐Ÿ’…

And since we have the average real-time and the percentage spent in each state, we can easily math out the time spent in each state by multiplying Average thread real-time with Thread state %. So like, to get the time Scheduler 1 spent in the emulator state we do 1000513us * 0.13% = 1300us. slay math. ๐Ÿงฎโœจ


๐ŸŒˆ DATA TYPES ๐ŸŒˆ

msacc_data() :: [msacc_data_thread()].
msacc_data_counters() :: #{msacc_state() => non_neg_integer()}.

A map holding the different microstate accounting states and the number of microseconds spent in each one. ๐Ÿ•ฐ๏ธ

msacc_data_thread() ::
    #{'$type' := msacc_data,
      type := msacc_type(),
      id := msacc_id(),
      counters := msacc_data_counters()}.
msacc_id() :: non_neg_integer().
msacc_print_options() :: #{system => boolean()}.

The different options you can hand to print/2. ๐ŸŽ€

msacc_state() ::
    alloc | aux | bif | busy_wait | check_io | emulator | ets |
    gc | gc_fullsweep | nif | other | port | send | sleep |
    timers.

The different states a thread can be in. See erlang:statistics(microstate_accounting) for the details, bestie. ๐Ÿ‘€

msacc_stats() :: [msacc_stats_thread()].
msacc_stats_counters() ::
    #{msacc_state() => #{thread := float(), system := float()}}.

A map with the different microstate accounting states. Each value in the map holds another map with the percentage of time that this thread spent in the specific state. Both the percentage of system time and the time for that specific thread are part of the map. ๐Ÿ’–

msacc_stats_thread() ::
    #{'$type' := msacc_stats,
      type := msacc_type(),
      id := msacc_id(),
      system := float(),
      counters := msacc_stats_counters()}.

A map with info about one specific thread. The percentages inside can be either run-time or real-time, depending on whether runtime or realtime was requested from stats/2. And system is the percentage of total system time for this specific thread. ๐Ÿซถ

msacc_type() ::
    aux | async | dirty_cpu_scheduler | dirty_io_scheduler |
    poll | scheduler.

๐Ÿ‘‘ FUNCTIONS ๐Ÿ‘‘

โœจ available() -> boolean().

This function checks whether microstate accounting is even available or not. vibe check. โœ…

โœจ from_file(Filename) -> msacc_data()

from_file(Filename) -> msacc_data()
                    when Filename :: file:name_all().

Reads a file dump that was produced by to_file(Filename). ๐Ÿ“‚

Prints the current microstate accounting to standard out. Equivalent to msacc:print(msacc:stats(), #{}). ๐Ÿ–จ๏ธ

print(DataOrStats, Options) -> ok
                when
                    DataOrStats :: msacc_data() | msacc_stats(),
                    Options :: msacc_print_options().

Prints the given microstate statistics values to standard out. Heads up: with many states this can get verbose. See the top of this reference manual for a quick rundown of what the fields mean. ๐Ÿ“

You can print more specific types of stats by first manipulating the DataOrStats using stats/2. So for instance, if you wanna print the percentage of run-time for each thread you can do:

msacc:print(msacc:stats(runtime, msacc:stats())).

And if you only wanna print run-time per thread type, you can do:

msacc:print(msacc:stats(type, msacc:stats(runtime, msacc:stats()))).

Options

  • system โ€” Print percentage of time spent in each state out of system time as well as thread time. Default: false.
print(FileOrDevice, DataOrStats, Options) -> ok
                when
                    FileOrDevice :: file:filename() | io:device(),
                    DataOrStats :: msacc_data() | msacc_stats(),
                    Options :: msacc_print_options().

Prints the given microstate statistics values to the given file or device. The other arguments behave exactly the same way as they do for print/2. ๐Ÿ’ซ

โœจ reset() -> boolean().

Resets the microstate accounting counters. Returns whether it was enabled or disabled. ๐Ÿ”„

โœจ start() -> boolean().

Starts microstate accounting. Returns whether it was previously enabled or disabled. ๐Ÿš€

โœจ start(Time) -> true

start(Time) -> true when Time :: timeout().

Resets all counters and then starts microstate accounting for the given number of milliseconds. โฑ๏ธ

โœจ stats() -> msacc_data().

Returns a runtime system independent version of the microstate statistics data presented by erlang:statistics(microstate_accounting). All counters have been normalized to be in microsecond resolution. ๐ŸŽฏ

โœจ stats(Analysis, Stats)

stats(Analysis, Stats) -> non_neg_integer()
                when
                    Analysis :: system_realtime | system_runtime,
                    Stats :: msacc_data();
            (Analysis, Stats) -> msacc_stats()
                when
                    Analysis :: realtime | runtime, Stats :: msacc_data();
            (Analysis, StatsOrData) -> msacc_data() | msacc_stats()
                when
                    Analysis :: type,
                    StatsOrData :: msacc_data() | msacc_stats().

Returns the system time for the given microstate statistics values. System time = the accumulated time of all threads. ๐Ÿ’–

  • realtime โ€” Returns all time recorded for all threads.
  • runtime โ€” Returns all time spent doing work for all threads, i.e. all time not spent in the sleep state. ๐Ÿ˜ด๐Ÿšซ

Returns fractions of real-time or run-time spent in the various threads from the given microstate statistics values. ๐Ÿ“Š

Returns a list of microstate statistics values where the values for all threads of the same type have been merged. ๐Ÿงฌ

โœจ stop() -> boolean().

Stops microstate accounting. Returns whether it was previously enabled or disabled. ๐Ÿ›‘

โœจ to_file(Filename) -> ok | {error, file:posix()}

to_file(Filename) -> ok | {error, file:posix()}
                  when Filename :: file:name_all().

Dumps the current microstate statistics counters to a file that can be parsed with file:consult/1. ๐Ÿ’พ


and that's the whole page, bestie!! ๐ŸŽ€โœจ

This little masterpiece is brought to you by Ericsson AB, shipped as part of runtime_tools 2.4, and it's the msacc(3) page itself. go forth and count them microseconds. ๐Ÿ’…๐Ÿฆ‹๐ŸŒŸ

๐Ÿ“ฆ where this page comes from