0
0
mirror of https://github.com/yse/easy_profiler.git synced 2024-12-27 00:31:02 +08:00

Store context switch timestamp on linux.

It's need to run systemtap util for loading kernel module. This kernel module capture context switch timestamp and systemtap store it in the temp file.
Before running profiling application you should run systemtap script with root privileges as following:
\# stap -o /tmp/cs_profiling_info.log scripts/context_switch_logger.stp name APPLICATION_NAME
where APPLICATION_NAME is profiling application
This commit is contained in:
Sergey Yagovtsev 2016-09-05 22:11:03 +03:00
parent 6d1b9915d2
commit 9521f8ac02
4 changed files with 97 additions and 5 deletions

View File

@ -219,6 +219,8 @@ namespace profiler {
void PROFILER_API setEnabled(bool isEnable);
uint32_t PROFILER_API dumpBlocksToFile(const char* filename);
void PROFILER_API setThreadName(const char* name, const char* filename, const char* _funcname, int line);
void PROFILER_API setContextSwitchLogFilename(const char* name);
const char* PROFILER_API getContextSwitchLogFilename();
}
typedef uint64_t timestamp_t;

View File

@ -0,0 +1,36 @@
global target_pid
global target_name
probe scheduler.ctxswitch {
if (target_pid != 0
&& next_pid != target_pid
&& prev_pid != target_pid)
next
if (target_name != ""
&& prev_task_name != target_name
&& next_task_name != target_name)
next
//printf("Switch from %d(%s) to %d(%s) at %d\n",prev_tid, prev_task_name,next_tid,next_task_name, gettimeofday_ns())
printf("%d %d %d\n",gettimeofday_ns(),prev_tid, next_tid )
}
probe begin
{
target_pid = 0
target_name = ""
%( $# == 1 || $# > 2 %?
log("Wrong number of arguments, use none, 'pid nr' or 'name proc'")
exit()
%)
%( $# == 2 %?
if(@1 == "pid")
target_pid = strtol(@2, 10)
if(@1 == "name")
target_name = @2
%)
}

View File

@ -26,10 +26,12 @@ extern "C"{
void PROFILER_API setEnabled(bool isEnable)
{
MANAGER.setEnabled(isEnable);
#ifdef _WIN32
if (isEnable)
EasyEventTracer::instance().enable(true);
else
EasyEventTracer::instance().disable();
#endif
}
void PROFILER_API beginBlock(Block& _block)
@ -47,6 +49,16 @@ extern "C"{
return MANAGER.setThreadName(name, filename, _funcname, line);
}
void PROFILER_API setContextSwitchLogFilename(const char* name)
{
return MANAGER.setContextSwitchLogFilename(name);
}
const char* PROFILER_API getContextSwitchLogFilename()
{
return MANAGER.getContextSwitchLogFilename();
}
}
SerializedBlock::SerializedBlock(const Block& block, uint16_t name_length)
@ -165,6 +177,16 @@ void ProfileManager::_cswitchBeginBlock(profiler::timestamp_t _time, profiler::b
thread_storage->sync.openedList.emplace(_time, profiler::BLOCK_TYPE_CONTEXT_SWITCH, _id, "");
}
void ProfileManager::_cswitchStoreBlock(profiler::timestamp_t _time, profiler::block_id_t _id, profiler::thread_id_t _thread_id)
{
auto thread_storage = _threadStorage(_thread_id);
if (thread_storage != nullptr){
profiler::Block lastBlock(_time, profiler::BLOCK_TYPE_CONTEXT_SWITCH, _id, "");
lastBlock.finish(_time);
thread_storage->storeCSwitch(lastBlock);
}
}
void ProfileManager::endBlock()
{
if (!m_isEnabled)
@ -236,6 +258,25 @@ uint32_t ProfileManager::dumpBlocksToFile(const char* filename)
if (wasEnabled)
::profiler::setEnabled(false);
#ifndef _WIN32
uint64_t timestamp;
uint32_t thread_from, thread_to;
std::ifstream infile(m_csInfoFilename.c_str());
if(infile.is_open())
{
while (infile >> timestamp >> thread_from >> thread_to )
{
static const ::profiler::StaticBlockDescriptor desc("OS.ContextSwitch", __FILE__, __LINE__, ::profiler::BLOCK_TYPE_CONTEXT_SWITCH, ::profiler::colors::White);
_cswitchBeginBlock(timestamp, desc.id(), thread_from);
_cswitchEndBlock(thread_to, timestamp);
}
}
#endif
FileWriter of(filename);
uint64_t usedMemorySize = 0;

View File

@ -150,6 +150,8 @@ class ProfileManager final
profiler::spin_lock m_storedSpin;
bool m_isEnabled = false;
std::string m_csInfoFilename = "/tmp/cs_profiling_info.log";
public:
static ProfileManager& instance();
@ -161,7 +163,18 @@ public:
uint32_t dumpBlocksToFile(const char* filename);
void setThreadName(const char* name, const char* filename, const char* _funcname, int line);
void setContextSwitchLogFilename(const char* name)
{
m_csInfoFilename = name;
}
const char* getContextSwitchLogFilename() const
{
return m_csInfoFilename.c_str();
}
void _cswitchBeginBlock(profiler::timestamp_t _time, profiler::block_id_t _id, profiler::thread_id_t _thread_id);
void _cswitchStoreBlock(profiler::timestamp_t _time, profiler::block_id_t _id, profiler::thread_id_t _thread_id);
void _cswitchEndBlock(profiler::thread_id_t _thread_id, profiler::timestamp_t _endtime);
private: