Lightweight Logging Library for Multi-Threading.
cd examples/mandelbrot
make
./mandelbrot
cd ../../
./run_viewer.bash examples/mandelbrot/mlog.txt
For more details about Mandelbrot example, see examples/mandelbrot/README.md.
mkdir build
cd build
cmake ..
make
make check
typedef struct mlog_data { /* implementation defined */ } mlog_data_t;
Log buffering structure for a whole MassiveLogger environment.
void mlog_init(mlog_data_t* md, int num_ranks, size_t buf_size);
Parameters:
md
: Pointer to amlog_data_t
variable at global scope.num_ranks
: The number of ranks (e.g., the number of workers/threads using MassiveLogger).buf_size
: The minimum unit of buffer memory size. The current implementation first allocates 2 *buf_size
bytes of memory for each rank.
void* MLOG_BEGIN(mlog_data_t* md, int rank, ...);
Parameters:
md
: Pointer to amlog_data_t
variable at global scope.rank
: e.g., worker ID or thread ID....
: Arguments to record.
Return value:
- Pointer to the recorded data (
begin_ptr
). This should be passed toMLOG_END
function.
void MLOG_END(mlog_data_t* md, int rank, void* begin_ptr, void* (*decoder)(FILE*, int, int, void*, void*), ...);
Parameters:
md
: Pointer to amlog_data_t
variable at global scope.rank
: e.g., worker ID or thread ID.begin_ptr
: The return value ofMLOG_BEGIN
function.decoder
: Function pointer to a decorder function that transfers recorded data into formatted string. This is called when outputting recorded data to files. See below for more details....
: Arguments to record.
decoder
should be defined as follows.
void* decoder(FILE* stream, int rank0, int rank1, void* buf0, void* buf1);
Parameters:
stream
: File stream to write output.rank0
: Who callsMLOG_BEGIN
.rank1
: Who callsMLOG_END
.buf0
: Pointer to the beginning of the recorded arguments inMLOG_BEGIN
.buf1
: Pointer to the beginning of the recorded arguments inMLOG_END
.
Return value:
- Pointer to the end of the recorded arguments in
MLOG_END
. You can useMLOG_READ_ARG
macro to read args, and when you have read all recorded args,buf1
should be the return value.
void MLOG_PRINTF(mlog_data_t* md, int rank, char* format, ...);
Parameters:
md
: Pointer to amlog_data_t
variable at global scope.rank
: e.g., worker ID or thread ID.format
: Format string (usually passed toprintf
function)....
: Arguments to record.
Note:
- Arguments passed to
MLOG_PRINTF
are not converted to string whenMLOG_PRINTF
is called. They are converted to string whenmlog_flush
is called. - Due to its implementation, type is more strict than
printf
. Withprintf
, types of arguments are automatically converted (e.g., float is converted to double), but withMLOG_PRINTF
, they are not converted. Therefore you should explicitly specify types informat
and to arguments (seetests/printf_test.c
). - This is different from the C standard, but you must use "%f" with float. If you want to record double value, you should use "%lf" specifier.
- "%n" is not supported.
- Currently variable field width
*
specifier (e.g.,"%.*s"
) is not supported.
void mlog_flush(mlog_data_t* md, int rank, FILE* stream);
Parameters:
md
: Pointer to amlog_data_t
variable at global scope.rank
: Logs in the end buffer ofrank
are flushed.stream
: Logs are written tostream
.
void mlog_flush_all(mlog_data_t* md, FILE* stream);
Parameters:
md
: Pointer to amlog_data_t
variable at global scope.stream
: All logs are written tostream
.
#define MLOG_READ_ARG(/* void** */ buf, type) /* ... */
Parameters:
buf
: Pointer to the buffer pointer. The buffer pointer is advanced bysizeof(type)
.type
: Type of the stored value.
Return value:
- Value loaded from buffer.
void mlog_warmup(mlog_data_t* md, int rank);
Write some values to entire buffers to avoid page faults while recording.
Parameters:
md
: Pointer to amlog_data_t
variable at global scope.rank
: e.g., worker ID or thread ID.
Note:
- You should be aware of NUMA effect; that is, if the memory allocation policy is
first-touch
policy, buffers are allocated to a NUMA node wheremlog_warmup()
is called. If you warm-up all threads' buffers in the main thread, all of buffers are allocated to a single NUMA node, which causes performance degradation in NUMA environment.
void* mlog_begin_tl(mlog_data_t* md, int rank);
rank
and a timestamp (the return value of mlog_clock_gettime_in_nsec()
) are recorded to the begin buffer.
Parameters:
md
: Pointer to amlog_data_t
variable at global scope.rank
: e.g., worker ID or thread ID.
Return value:
- A pointer to the recorded data (
begin_ptr
). This should be passed tomlog_end_tl
function.
void mlog_end_tl(mlog_data_t* md, int rank, void* begin_ptr, char* event_name);
rank
, a timestamp (the return value of mlog_clock_gettime_in_nsec()
), and event_name
are recorded to the end buffer.
Parameters:
md
: Pointer to amlog_data_t
variable at global scope.rank
: e.g., worker ID or thread ID.begin_ptr
: The return value ofmlog_begin_tl
function.event_name
: Event name to be recorded.
uint64_t mlog_gettimeofday_in_usec();
Return the value of gettimeofday
in micro seconds.
uint64_t mlog_clock_gettime_in_nsec();
Return the value of clock_gettime
in nano seconds.
CLOCK_MONOTONIC
option is specified to clock_gettime
.
uint64_t mlog_rdtsc();
Return the value of rdtsc
instruction.
How to set flags:
#define MLOG_XXX 1
#include <mlog/mlog.h>
Disable checking the size of begin and end buffer with every log call (default: 0). Disabling the check may speed up the logging feature, but it can cause segmentation fault (unsafe).
Disable realloc of start and end buffer when buffers become full (default: 0). When this flag is set and buffers become full, the execution is aborted without resizing buffers. This prevents unconscious overheads with reallocation when measuring the performance.
- By default, the viewer is automatically terminated when the first web session is closed.
We can make the server lifetime permanent by setting an environment variable
MLOG_VIEWER_ONESHOT=false
.
MLOG_BEGIN
and MLOG_END
:
buf0
|
v
-----------------------------------------------------------------------------------
rank0 | | |
... | arg1 | arg2 | ...
begin_buf | | |
-----------------------------------------------------------------------------------
^
| buf1
| |
| v
-----------------------------------------------------------------------------------
rank1 | | | | | | |
... | begin_ptr | decoder | arg1 | arg2 | ... | begin_ptr | ...
end_buf | | | | | | |
-----------------------------------------------------------------------------------
MLOG_PRINTF
:
-----------------------------------------------------------------------------------
| | | | | | |
end_buf ... | NULL | format | arg1 | arg2 | ... | NULL | ...
| | | | | | |
-----------------------------------------------------------------------------------
MassiveLogger is distributed under the 2-Clause BSD License. See LICENSE for further information.