Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement enable function tracing for DFTracer. #184

Merged
merged 4 commits into from
Sep 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@
"typeinfo": "cpp",
"valarray": "cpp",
"variant": "cpp",
"ranges": "cpp"
"ranges": "cpp",
"filesystem": "cpp",
"*.in": "cpp"
}
}
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ set(DFTRACER_PRELOAD_PRIVATE_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/df

set(DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/brahma/posix.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/brahma/stdio.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/finstrument/functions.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/writer/chrome_writer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/posix_internal.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/dftracer.cpp
Expand All @@ -270,6 +271,7 @@ set(DFTRACER_CORE_PUBLIC_INCLUDE
set(DFTRACER_CORE_PRIVATE_INCLUDE
${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/posix_internal.h
${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/utils.h
${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/finstrument/functions.h
${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/brahma/posix.h
${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/brahma/stdio.h
${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/dftracer_main.h
Expand Down
1 change: 1 addition & 0 deletions cmake/configure_files/dftracer-config.cmake.build.in
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ if (DFTRACER_INCLUDE_MPI)
endif ()
endif()

set(DFTRACER_FUNCTION_FLAGS "-g" "-finstrument-functions" "-Wl,-E" "-fvisibility=default")
check_required_components(dftracer)

set(DFTRACER_LIBRARIES dftracer)
1 change: 1 addition & 0 deletions cmake/configure_files/dftracer-config.cmake.install.in
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ if (DFTRACER_INCLUDE_MPI)
message(FATAL_ERROR "-- [DFTRACER] mpi is needed for ${PROJECT_NAME} build")
endif ()
endif()
set(DFTRACER_FUNCTION_FLAGS "-g" "-finstrument-functions" "-Wl,-E" "-fvisibility=default")

check_required_components(dftracer)

Expand Down
13 changes: 13 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,19 @@ The name passed to the function should be unique in every scope.
DFTRACER_C_FUNCTION_END(); // END FUNCTION foo.
}

----------------------------------------
DFTracer C/C++ Function Profiling using GCC
----------------------------------------

GCC supports function level tracing using ``-finstrument-functions``.
DFTracer allows application to compile with ``-g -finstrument-functions -Wl,-E -fvisibility=default``.
If the applications are using cmake, they can find_package and then use the CMAKE Variable `DFTRACER_FUNCTION_FLAGS` for compile flags.
This can be applied globally or on a target.

Internally DFTracer uses ``dladdr`` to resolve symbol names which work for shared libraries.
For executables or binaries, we store the address and the name which can be used to derive the function name at analysis time.
This can be done using ``nm -D`` or ``readelf -S`` utilities.

-------------------------
DFTracer Python APIs
-------------------------
Expand Down
8 changes: 8 additions & 0 deletions src/dftracer/core/dftracer_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Created by haridev on 10/8/23.
//
#include <dftracer/core/dftracer_main.h>
#include <dftracer/finstrument/functions.h>
template <>
std::shared_ptr<dftracer::DFTracerCore>
dftracer::Singleton<dftracer::DFTracerCore>::instance = nullptr;
Expand Down Expand Up @@ -109,6 +110,10 @@ bool dftracer::DFTracerCore::finalize() {
if (stdio_instance != nullptr) {
stdio_instance->finalize();
}
auto function_instance = dftracer::Function::get_instance();
if (function_instance != nullptr) {
function_instance->finalize();
}
}
if (logger != nullptr) {
logger->finalize();
Expand Down Expand Up @@ -234,7 +239,10 @@ void dftracer::DFTracerCore::initialize(bool _bind, const char *_log_file,
brahma::STDIODFTracer::get_instance(conf->trace_all_files);
}
}
dftracer::Function::get_instance();
}
} else {
dftracer::Function::get_instance()->finalize();
}
is_initialized = true;
}
Expand Down
74 changes: 74 additions & 0 deletions src/dftracer/finstrument/functions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include <dftracer/finstrument/functions.h>
#include <link.h>
std::shared_ptr<dftracer::Function> dftracer::Function::instance = nullptr;

thread_local std::unordered_map<std::string, TimeResolution>
dftracer::Function::map = std::unordered_map<std::string, TimeResolution>();
bool dftracer::Function::stop_trace = false;
int dftracer::Function::enter_event(std::string &name) {
if (stop_trace) return -1;
auto start = this->logger->get_time();
map.insert_or_assign(name, start);
return 0;
}

int dftracer::Function::exit_event(std::string &name, TimeResolution &start) {
if (stop_trace) return -1;
auto tmap = map.find(name);
if (tmap != map.end()) {
start = tmap->second;
map.erase(name);
return 0;
}
return -1;
}

void __cyg_profile_func_enter(void *func, void *caller) {
auto function = dftracer::Function::get_instance();
if (!function->is_active()) return;
Dl_info info;
if (!dladdr(func, &info)) return;
if (!info.dli_fname) return;
std::string event_name;
if (!info.dli_sname) {
char name[256];
sprintf(name, "%p", func);
event_name = name;
} else {
event_name = info.dli_sname;
}

DFTRACER_LOG_DEBUG("Calling function %s", event_name);
function->enter_event(event_name);
}

void __cyg_profile_func_exit(void *func, void *caller) {
auto function = dftracer::Function::get_instance();
auto end_time = function->logger->get_time();
if (!function->is_active()) return;
Dl_info info;
if (!dladdr(func, &info)) return;
if (!info.dli_fname) return;
std::string event_name;
if (!info.dli_sname) {
char name[256];
sprintf(name, "%p", func);
event_name = name;
} else {
event_name = info.dli_sname;
}
TimeResolution start_time;
int status = function->exit_event(event_name, start_time);
if (status == 0) {
std::unordered_map<std::string, std::any> *metadata;
if (function->logger->include_metadata) {
metadata = new std::unordered_map<std::string, std::any>();
const char *so = info.dli_fname;
metadata->insert_or_assign("so", so);
}
function->logger->enter_event();
function->logger->log(event_name.c_str(), CATEGORY, start_time,
end_time - start_time, metadata);
function->logger->exit_event();
}
}
61 changes: 61 additions & 0 deletions src/dftracer/finstrument/functions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//
// Created by hariharan on 8/8/22.
//

#ifndef DFTRACER_FUNCTION_H
#define DFTRACER_FUNCTION_H

/* Internal Header */
#include <dftracer/core/logging.h>
#include <dftracer/core/typedef.h>
#include <dftracer/df_logger.h>
#include <dftracer/utils/posix_internal.h>
/* External Header */
#include <dlfcn.h>

#include <memory>
#include <mutex>
#include <shared_mutex>
#include <unordered_map>

static ConstEventNameType CATEGORY = "FUNC";
extern "C" {
void __cyg_profile_func_enter(void *, void *)
__attribute__((no_instrument_function));
void __cyg_profile_func_exit(void *, void *)
__attribute__((no_instrument_function));
}
namespace dftracer {
class Function {
private:
static std::shared_ptr<Function> instance;
static bool stop_trace;
thread_local static std::unordered_map<std::string, TimeResolution> map;

public:
std::shared_ptr<DFTLogger> logger;
Function() {
DFTRACER_LOG_DEBUG("Function class intercepted", "");
logger = DFT_LOGGER_INIT();
}

void finalize() {
DFTRACER_LOG_DEBUG("Finalizing Function", "");
stop_trace = true;
}
~Function() {}
static std::shared_ptr<Function> get_instance() {
DFTRACER_LOG_DEBUG("POSIX class get_instance", "");
if (!stop_trace && instance == nullptr) {
instance = std::make_shared<Function>();
}
return instance;
}
bool is_active() { return !stop_trace; }
int enter_event(std::string &name);
int exit_event(std::string &name, TimeResolution &start);
};

} // namespace dftracer

#endif // DFTRACER_FUNCTION_H
7 changes: 6 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,15 @@ target_link_libraries(test_cpp ${PROJECT_NAME})
add_dependencies(test_cpp ${PROJECT_NAME})
add_dependencies(test_cpp ${PROJECT_NAME}_preload)

add_library(testlib SHARED c/testlib.c)
target_compile_options(testlib PRIVATE "-g" "-finstrument-functions" "-Wl,-E" "-fvisibility=default")
add_executable(test_c c/test.c)
target_link_libraries(test_c ${PROJECT_NAME})
target_compile_options(test_c PRIVATE "-g" "-finstrument-functions" "-Wl,-E" "-fvisibility=default")
target_link_libraries(test_c ${PROJECT_NAME} testlib)
add_dependencies(test_c ${PROJECT_NAME})
add_dependencies(test_c ${PROJECT_NAME}_preload)


function(set_common_properties test_name)
set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_LEVEL=DEBUG)
set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_TRACE_COMPRESSION=0)
Expand Down
3 changes: 3 additions & 0 deletions test/c/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>

int bar();
void foo() {
DFTRACER_C_FUNCTION_START();
DFTRACER_C_FUNCTION_UPDATE_INT("key", 0);
Expand All @@ -16,6 +18,7 @@ void foo() {
DFTRACER_C_REGION_START(CUSTOM);
DFTRACER_C_REGION_UPDATE_INT(CUSTOM, "key", 0);
DFTRACER_C_REGION_UPDATE_STR(CUSTOM, "key", "0");
bar();
sleep(1);
DFTRACER_C_REGION_START(CUSTOM_BLOCK);
sleep(1);
Expand Down
1 change: 1 addition & 0 deletions test/c/testlib.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int bar() { return 0; }
Loading