Lightweight Logging Library for Multi-Threading.
cd examples/mandelbrot
make
./mandelbrot
cd ../../
./run_viewer.bash examples/mandelbrot/mlog.txtFor more details about Mandelbrot example, see examples/mandelbrot/README.md.
mkdir build
cd build
cmake ..
make
make checktypedef 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_tvariable 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_sizebytes of memory for each rank.
void* MLOG_BEGIN(mlog_data_t* md, int rank, ...);Parameters:
md: Pointer to amlog_data_tvariable 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_ENDfunction.
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_tvariable at global scope.rank: e.g., worker ID or thread ID.begin_ptr: The return value ofMLOG_BEGINfunction.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_ARGmacro to read args, and when you have read all recorded args,buf1should be the return value.
void MLOG_PRINTF(mlog_data_t* md, int rank, char* format, ...);Parameters:
md: Pointer to amlog_data_tvariable at global scope.rank: e.g., worker ID or thread ID.format: Format string (usually passed toprintffunction)....: Arguments to record.
Note:
- Arguments passed to
MLOG_PRINTFare not converted to string whenMLOG_PRINTFis called. They are converted to string whenmlog_flushis 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 informatand 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_tvariable at global scope.rank: Logs in the end buffer ofrankare flushed.stream: Logs are written tostream.
void mlog_flush_all(mlog_data_t* md, FILE* stream);Parameters:
md: Pointer to amlog_data_tvariable 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_tvariable 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-touchpolicy, 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_tvariable 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_tlfunction.
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_tvariable at global scope.rank: e.g., worker ID or thread ID.begin_ptr: The return value ofmlog_begin_tlfunction.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.
