* Only pass functions with a size > 0 to the kernel. They would never
yield any hits anyway. The size 0 functions are hand-coded assembly functions (syscalls etc.). * Increased the requested sampling interval to 1 ms. Should be specifiable per command line. * Improved the output when done profiling a thread. The hit functions are sorted and printed in a table. * Some cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27571 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
76ef98dd3f
commit
ec38b40cc9
@ -9,6 +9,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
#include <debugger.h>
|
#include <debugger.h>
|
||||||
@ -43,6 +44,17 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct hit_symbol {
|
||||||
|
int64 hits;
|
||||||
|
Symbol* symbol;
|
||||||
|
|
||||||
|
inline bool operator<(const hit_symbol& other) const
|
||||||
|
{
|
||||||
|
return hits > other.hits;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// TODO: Adjust!
|
// TODO: Adjust!
|
||||||
static const char* kUsage =
|
static const char* kUsage =
|
||||||
"Usage: %s [ <options> ] <command line>\n"
|
"Usage: %s [ <options> ] <command line>\n"
|
||||||
@ -209,12 +221,10 @@ main(int argc, const char* const* argv)
|
|||||||
size_t symbolSize;
|
size_t symbolSize;
|
||||||
while (debug_next_image_symbol(iterator, symbolName, sizeof(symbolName),
|
while (debug_next_image_symbol(iterator, symbolName, sizeof(symbolName),
|
||||||
&symbolType, &symbolLocation, &symbolSize) == B_OK) {
|
&symbolType, &symbolLocation, &symbolSize) == B_OK) {
|
||||||
//if (symbolSize == 0) {
|
|
||||||
// printf(" %s %p (%6lu) %s\n",
|
// printf(" %s %p (%6lu) %s\n",
|
||||||
// symbolType == B_SYMBOL_TYPE_TEXT ? "text" : "data",
|
// symbolType == B_SYMBOL_TYPE_TEXT ? "text" : "data",
|
||||||
// symbolLocation, symbolSize, symbolName);
|
// symbolLocation, symbolSize, symbolName);
|
||||||
//}
|
if (symbolSize > 0 && symbolType == B_SYMBOL_TYPE_TEXT) {
|
||||||
if (symbolType == B_SYMBOL_TYPE_TEXT) {
|
|
||||||
Symbol* symbol = new(std::nothrow) Symbol(
|
Symbol* symbol = new(std::nothrow) Symbol(
|
||||||
(addr_t)symbolLocation, symbolSize, symbolName);
|
(addr_t)symbolLocation, symbolSize, symbolName);
|
||||||
if (symbol == NULL || !symbols.AddItem(symbol)) {
|
if (symbol == NULL || !symbols.AddItem(symbol)) {
|
||||||
@ -248,7 +258,7 @@ main(int argc, const char* const* argv)
|
|||||||
|
|
||||||
startProfiler->reply_port = debugContext.reply_port;
|
startProfiler->reply_port = debugContext.reply_port;
|
||||||
startProfiler->thread = thread;
|
startProfiler->thread = thread;
|
||||||
startProfiler->interval = 10;
|
startProfiler->interval = 1000;
|
||||||
startProfiler->function_count = symbolCount;
|
startProfiler->function_count = symbolCount;
|
||||||
|
|
||||||
for (int32 i = 0; i < symbolCount; i++) {
|
for (int32 i = 0; i < symbolCount; i++) {
|
||||||
@ -314,27 +324,54 @@ main(int argc, const char* const* argv)
|
|||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case B_DEBUGGER_MESSAGE_PROFILER_STOPPED:
|
case B_DEBUGGER_MESSAGE_PROFILER_STOPPED:
|
||||||
printf("B_DEBUGGER_MESSAGE_PROFILER_STOPPED\n");
|
{
|
||||||
printf(" total ticks: %lld, missed: %lld\n",
|
int64 totalTicks = message->profiler_stopped.total_ticks;
|
||||||
message->profiler_stopped.total_ticks,
|
int64 missedTicks = message->profiler_stopped.missed_ticks;
|
||||||
message->profiler_stopped.missed_ticks);
|
bigtime_t interval = message->profiler_stopped.interval;
|
||||||
|
|
||||||
|
printf("\nprofiling results for thread %ld:\n",
|
||||||
|
message->profiler_stopped.origin.thread);
|
||||||
|
printf(" tick interval: %lld us\n", interval);
|
||||||
|
printf(" total ticks: %lld (%lld us)\n", totalTicks,
|
||||||
|
totalTicks * interval);
|
||||||
|
printf(" missed ticks: %lld (%lld us, %6.2f%%)\n",
|
||||||
|
missedTicks, missedTicks * interval,
|
||||||
|
100.0 * missedTicks / totalTicks);
|
||||||
|
|
||||||
|
// find and sort the hit symbols
|
||||||
|
hit_symbol hitSymbols[symbolCount];
|
||||||
|
int32 hitSymbolCount = 0;
|
||||||
|
|
||||||
for (int32 i = 0; i < symbolCount; i++) {
|
for (int32 i = 0; i < symbolCount; i++) {
|
||||||
int64 hits = message->profiler_stopped.function_ticks[i];
|
int64 hits = message->profiler_stopped.function_ticks[i];
|
||||||
if (hits > 0)
|
if (hits > 0) {
|
||||||
printf("%10lld %s\n", hits, symbols.ItemAt(i)->Name());
|
hit_symbol& hitSymbol = hitSymbols[hitSymbolCount++];
|
||||||
|
hitSymbol.hits = hits;
|
||||||
|
hitSymbol.symbol = symbols.ItemAt(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
if (hitSymbolCount > 1)
|
||||||
/*
|
std::sort(hitSymbols, hitSymbols + hitSymbolCount);
|
||||||
typedef struct {
|
|
||||||
debug_origin origin;
|
|
||||||
int32 function_count;
|
|
||||||
int64 total_ticks; // total number of sample ticks
|
|
||||||
int64 missed_ticks; // ticks that didn't hit a function
|
|
||||||
int64 function_ticks[1]; // number of hits for each function
|
|
||||||
} debug_profiler_stopped;
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
if (hitSymbolCount > 0) {
|
||||||
|
printf("\n");
|
||||||
|
printf(" hits in us in %% function\n");
|
||||||
|
printf(" -------------------------------------------------"
|
||||||
|
"-----------------------------\n");
|
||||||
|
for (int32 i = 0; i < hitSymbolCount; i++) {
|
||||||
|
const hit_symbol& hitSymbol = hitSymbols[i];
|
||||||
|
const Symbol* symbol = hitSymbol.symbol;
|
||||||
|
printf(" %10lld %10lld %6.2f %s\n", hitSymbol.hits,
|
||||||
|
hitSymbol.hits * interval,
|
||||||
|
100.0 * hitSymbol.hits / totalTicks,
|
||||||
|
symbol->Name());
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
printf(" no functions were hit\n");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case B_DEBUGGER_MESSAGE_POST_SYSCALL:
|
case B_DEBUGGER_MESSAGE_POST_SYSCALL:
|
||||||
case B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED:
|
case B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED:
|
||||||
@ -367,37 +404,7 @@ typedef struct {
|
|||||||
continue_thread(message->origin.nub_port, message->origin.thread);
|
continue_thread(message->origin.nub_port, message->origin.thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
destroy_debug_context(&debugContext);
|
destroy_debug_context(&debugContext);
|
||||||
|
|
||||||
//kill_thread(thread);
|
|
||||||
//exit(0);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
typedef struct {
|
|
||||||
debug_origin origin;
|
|
||||||
int32 function_count;
|
|
||||||
int64 total_ticks; // total number of sample ticks
|
|
||||||
int64 missed_ticks; // ticks that didn't hit a function
|
|
||||||
int64 function_ticks[1]; // number of hits for each function
|
|
||||||
} debug_profiler_stopped;
|
|
||||||
|
|
||||||
struct debug_profile_function {
|
|
||||||
addr_t base; // function base address
|
|
||||||
size_t size; // function size
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
port_id reply_port; // port to send the reply to
|
|
||||||
thread_id thread; // thread to profile
|
|
||||||
bigtime_t interval; // sample interval
|
|
||||||
int32 function_count; // number of functions we count hits for
|
|
||||||
struct debug_profile_function functions[1];
|
|
||||||
// functions that shall be tracked
|
|
||||||
} debug_nub_start_profiler;
|
|
||||||
*/
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user