mirror of
https://github.com/yse/easy_profiler.git
synced 2024-12-26 08:01:51 +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:
parent
6d1b9915d2
commit
9521f8ac02
@ -214,11 +214,13 @@ namespace profiler {
|
||||
class StaticBlockDescriptor;
|
||||
|
||||
extern "C"{
|
||||
void PROFILER_API beginBlock(Block& _block);
|
||||
void PROFILER_API endBlock();
|
||||
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 beginBlock(Block& _block);
|
||||
void PROFILER_API endBlock();
|
||||
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;
|
||||
|
36
scripts/context_switch_logger.stp
Normal file
36
scripts/context_switch_logger.stp
Normal 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
|
||||
%)
|
||||
}
|
@ -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;
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user