* Also compute the number of CPUs and the idle time of each CPU.
* Show the CPU count and the total idle time in the "General" page. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34585 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
94a6d7ada8
commit
bea40bcd49
@ -15,12 +15,16 @@ MainWindow::GeneralPage::GeneralPage()
|
||||
AbstractGeneralPage(),
|
||||
fModel(NULL),
|
||||
fDataSourceView(NULL),
|
||||
fCPUCountView(NULL),
|
||||
fRunTimeView(NULL),
|
||||
fIdleTimeView(NULL),
|
||||
fTeamCountView(NULL),
|
||||
fThreadCountView(NULL)
|
||||
{
|
||||
fDataSourceView = AddDataView("Data Source:");
|
||||
fRunTimeView = AddDataView("Run Time:");
|
||||
fCPUCountView = AddDataView("Number of CPUs:");
|
||||
fRunTimeView = AddDataView("Total Time:");
|
||||
fIdleTimeView = AddDataView("Idle Time:");
|
||||
fTeamCountView = AddDataView("Teams:");
|
||||
fThreadCountView = AddDataView("Threads:");
|
||||
}
|
||||
@ -43,10 +47,25 @@ MainWindow::GeneralPage::SetModel(Model* model)
|
||||
// data source
|
||||
fDataSourceView->SetText(fModel->DataSourceName());
|
||||
|
||||
// run time
|
||||
// cpu count
|
||||
char buffer[128];
|
||||
fRunTimeView->SetText(format_nanotime(fModel->LastEventTime(), buffer,
|
||||
sizeof(buffer)));
|
||||
snprintf(buffer, sizeof(buffer), "%" B_PRId32, fModel->CountCPUs());
|
||||
fCPUCountView->SetText(buffer);
|
||||
|
||||
// run time
|
||||
nanotime_t runtime = fModel->LastEventTime();
|
||||
fRunTimeView->SetText(format_nanotime(runtime, buffer, sizeof(buffer)));
|
||||
|
||||
// idle time
|
||||
if (runtime == 0)
|
||||
runtime = 1;
|
||||
double idlePercentage = (double)fModel->IdleTime()
|
||||
/ (runtime * fModel->CountCPUs()) * 100;
|
||||
char timeBuffer[64];
|
||||
format_nanotime(fModel->IdleTime(), timeBuffer, sizeof(timeBuffer));
|
||||
snprintf(buffer, sizeof(buffer), "%s (%.2f %%)", timeBuffer,
|
||||
idlePercentage);
|
||||
fIdleTimeView->SetText(buffer);
|
||||
|
||||
// team count
|
||||
snprintf(buffer, sizeof(buffer), "%ld", fModel->CountTeams());
|
||||
@ -57,7 +76,9 @@ MainWindow::GeneralPage::SetModel(Model* model)
|
||||
fThreadCountView->SetText(buffer);
|
||||
} else {
|
||||
fDataSourceView->SetText("");
|
||||
fCPUCountView->SetText("");
|
||||
fRunTimeView->SetText("");
|
||||
fIdleTimeView->SetText("");
|
||||
fTeamCountView->SetText("");
|
||||
fThreadCountView->SetText("");
|
||||
}
|
||||
|
@ -22,7 +22,9 @@ public:
|
||||
private:
|
||||
Model* fModel;
|
||||
TextDataView* fDataSourceView;
|
||||
TextDataView* fCPUCountView;
|
||||
TextDataView* fRunTimeView;
|
||||
TextDataView* fIdleTimeView;
|
||||
TextDataView* fTeamCountView;
|
||||
TextDataView* fThreadCountView;
|
||||
};
|
||||
|
@ -14,6 +14,23 @@
|
||||
#include <AutoDeleter.h>
|
||||
|
||||
|
||||
// #pragma mark - CPU
|
||||
|
||||
|
||||
Model::CPU::CPU()
|
||||
:
|
||||
fIdleTime(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Model::CPU::SetIdleTime(nanotime_t time)
|
||||
{
|
||||
fIdleTime = time;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - WaitObject
|
||||
|
||||
|
||||
@ -445,8 +462,11 @@ Model::Model(const char* dataSourceName, void* eventData, size_t eventDataSize)
|
||||
fDataSourceName(dataSourceName),
|
||||
fEventData(eventData),
|
||||
fEventDataSize(eventDataSize),
|
||||
fCPUCount(1),
|
||||
fBaseTime(0),
|
||||
fLastEventTime(0),
|
||||
fIdleTime(0),
|
||||
fCPUs(20, true),
|
||||
fTeams(20, true),
|
||||
fThreads(20, true),
|
||||
fWaitObjectGroups(20, true),
|
||||
@ -469,8 +489,14 @@ Model::~Model()
|
||||
void
|
||||
Model::LoadingFinished()
|
||||
{
|
||||
// set the thread indices
|
||||
for (int32 i = 0; Thread* thread = fThreads.ItemAt(i); i++)
|
||||
thread->SetIndex(i);
|
||||
|
||||
// compute the total idle time
|
||||
fIdleTime = 0;
|
||||
for (int32 i = 0; CPU* cpu = CPUAt(i); i++)
|
||||
fIdleTime += cpu->IdleTime();
|
||||
}
|
||||
|
||||
|
||||
@ -488,6 +514,25 @@ Model::SetLastEventTime(nanotime_t time)
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Model::SetCPUCount(int32 count)
|
||||
{
|
||||
fCPUCount = count;
|
||||
|
||||
fCPUs.MakeEmpty();
|
||||
|
||||
for (int32 i = 0; i < fCPUCount; i++) {
|
||||
CPU* cpu = new(std::nothrow) CPU;
|
||||
if (cpu == NULL || !fCPUs.AddItem(cpu)) {
|
||||
delete cpu;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
Model::CountTeams() const
|
||||
{
|
||||
|
@ -33,6 +33,7 @@ class Model : public Referenceable {
|
||||
public:
|
||||
struct creation_time_id;
|
||||
struct type_and_object;
|
||||
class CPU;
|
||||
class WaitObjectGroup;
|
||||
class WaitObject;
|
||||
class ThreadWaitObject;
|
||||
@ -64,6 +65,12 @@ public:
|
||||
inline nanotime_t LastEventTime() const;
|
||||
void SetLastEventTime(nanotime_t time);
|
||||
|
||||
inline nanotime_t IdleTime() const;
|
||||
|
||||
inline int32 CountCPUs() const;
|
||||
bool SetCPUCount(int32 count);
|
||||
inline CPU* CPUAt(int32 index) const;
|
||||
|
||||
int32 CountTeams() const;
|
||||
Team* TeamAt(int32 index) const;
|
||||
Team* TeamByID(team_id id) const;
|
||||
@ -105,6 +112,7 @@ public:
|
||||
// returns the closest previous state
|
||||
|
||||
private:
|
||||
typedef BObjectList<CPU> CPUList;
|
||||
typedef BObjectList<Team> TeamList;
|
||||
typedef BObjectList<Thread> ThreadList;
|
||||
typedef BObjectList<WaitObjectGroup> WaitObjectGroupList;
|
||||
@ -118,8 +126,11 @@ private:
|
||||
BString fDataSourceName;
|
||||
void* fEventData;
|
||||
size_t fEventDataSize;
|
||||
int32 fCPUCount;
|
||||
nanotime_t fBaseTime;
|
||||
nanotime_t fLastEventTime;
|
||||
nanotime_t fIdleTime;
|
||||
CPUList fCPUs;
|
||||
TeamList fTeams; // sorted by ID
|
||||
ThreadList fThreads; // sorted by ID
|
||||
WaitObjectGroupList fWaitObjectGroups;
|
||||
@ -139,6 +150,18 @@ struct Model::type_and_object {
|
||||
};
|
||||
|
||||
|
||||
class Model::CPU {
|
||||
public:
|
||||
CPU();
|
||||
|
||||
inline nanotime_t IdleTime() const;
|
||||
void SetIdleTime(nanotime_t time);
|
||||
|
||||
private:
|
||||
nanotime_t fIdleTime;
|
||||
};
|
||||
|
||||
|
||||
class Model::WaitObject {
|
||||
public:
|
||||
WaitObject(
|
||||
@ -392,6 +415,7 @@ struct Model::CompactThreadSchedulingState {
|
||||
Model::Thread* thread;
|
||||
ThreadWaitObject* waitObject;
|
||||
ThreadState state;
|
||||
uint8 priority;
|
||||
|
||||
public:
|
||||
thread_id ID() const { return thread->ID(); }
|
||||
@ -519,6 +543,37 @@ Model::LastEventTime() const
|
||||
}
|
||||
|
||||
|
||||
nanotime_t
|
||||
Model::IdleTime() const
|
||||
{
|
||||
return fIdleTime;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
Model::CountCPUs() const
|
||||
{
|
||||
return fCPUCount;
|
||||
}
|
||||
|
||||
|
||||
Model::CPU*
|
||||
Model::CPUAt(int32 index) const
|
||||
{
|
||||
return fCPUs.ItemAt(index);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - CPU
|
||||
|
||||
|
||||
nanotime_t
|
||||
Model::CPU::IdleTime() const
|
||||
{
|
||||
return fIdleTime;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - WaitObject
|
||||
|
||||
|
||||
@ -995,6 +1050,7 @@ Model::CompactThreadSchedulingState::operator=(
|
||||
thread = other.thread;
|
||||
waitObject = other.waitObject;
|
||||
state = other.state;
|
||||
priority = other.priority;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,8 @@
|
||||
// add a scheduling state snapshot every x events
|
||||
static const uint32 kSchedulingSnapshotInterval = 1024;
|
||||
|
||||
static const uint32 kMaxCPUCount = 1024;
|
||||
|
||||
|
||||
struct SimpleWaitObjectInfo : system_profiler_wait_object_info {
|
||||
SimpleWaitObjectInfo(uint32 type)
|
||||
@ -44,6 +46,17 @@ static const SimpleWaitObjectInfo kSignalWaitObjectInfo(
|
||||
THREAD_BLOCK_TYPE_SIGNAL);
|
||||
|
||||
|
||||
struct ModelLoader::CPUInfo {
|
||||
nanotime_t idleTime;
|
||||
|
||||
CPUInfo()
|
||||
:
|
||||
idleTime(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
@ -64,13 +77,15 @@ ModelLoader::ModelLoader(DataSource* dataSource,
|
||||
:
|
||||
AbstractModelLoader(target, targetCookie),
|
||||
fModel(NULL),
|
||||
fDataSource(dataSource)
|
||||
fDataSource(dataSource),
|
||||
fCPUInfos(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ModelLoader::~ModelLoader()
|
||||
{
|
||||
delete[] fCPUInfos;
|
||||
delete fDataSource;
|
||||
delete fModel;
|
||||
}
|
||||
@ -102,6 +117,10 @@ ModelLoader::PrepareForLoading()
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
fCPUInfos = new(std::nothrow) CPUInfo[kMaxCPUCount];
|
||||
if (fCPUInfos == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -126,6 +145,9 @@ ModelLoader::FinishLoading(bool success)
|
||||
delete fModel;
|
||||
fModel = NULL;
|
||||
}
|
||||
|
||||
delete[] fCPUInfos;
|
||||
fCPUInfos = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -168,6 +190,7 @@ ModelLoader::_Load()
|
||||
}
|
||||
|
||||
// process the events
|
||||
fMaxCPUIndex = 0;
|
||||
fState.Clear();
|
||||
fBaseTime = -1;
|
||||
uint64 count = 0;
|
||||
@ -190,6 +213,12 @@ ModelLoader::_Load()
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
if (cpu > fMaxCPUIndex) {
|
||||
if (cpu + 1 > kMaxCPUCount)
|
||||
return B_BAD_DATA;
|
||||
fMaxCPUIndex = cpu;
|
||||
}
|
||||
|
||||
// periodically check whether we're supposed to abort
|
||||
if (++count % 32 == 0) {
|
||||
AutoLocker<BLocker> locker(fLock);
|
||||
@ -202,6 +231,12 @@ ModelLoader::_Load()
|
||||
fModel->AddSchedulingStateSnapshot(fState, offset);
|
||||
}
|
||||
|
||||
if (!fModel->SetCPUCount(fMaxCPUIndex + 1))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
for (uint32 i = 0; i <= fMaxCPUIndex; i++)
|
||||
fModel->CPUAt(i)->SetIdleTime(fCPUInfos[i].idleTime);
|
||||
|
||||
fModel->SetLastEventTime(fState.LastEventTime());
|
||||
fModel->LoadingFinished();
|
||||
|
||||
@ -311,7 +346,8 @@ ModelLoader::_ProcessEvent(uint32 event, uint32 cpu, const void* buffer,
|
||||
break;
|
||||
|
||||
case B_SYSTEM_PROFILER_THREAD_SCHEDULED:
|
||||
_HandleThreadScheduled((system_profiler_thread_scheduled*)buffer);
|
||||
_HandleThreadScheduled(cpu,
|
||||
(system_profiler_thread_scheduled*)buffer);
|
||||
break;
|
||||
|
||||
case B_SYSTEM_PROFILER_THREAD_ENQUEUED_IN_RUN_QUEUE:
|
||||
@ -320,7 +356,7 @@ ModelLoader::_ProcessEvent(uint32 event, uint32 cpu, const void* buffer,
|
||||
break;
|
||||
|
||||
case B_SYSTEM_PROFILER_THREAD_REMOVED_FROM_RUN_QUEUE:
|
||||
_HandleThreadRemovedFromRunQueue(
|
||||
_HandleThreadRemovedFromRunQueue(cpu,
|
||||
(thread_removed_from_run_queue*)buffer);
|
||||
break;
|
||||
|
||||
@ -382,7 +418,8 @@ ModelLoader::_HandleThreadRemoved(system_profiler_thread_removed* event)
|
||||
|
||||
|
||||
void
|
||||
ModelLoader::_HandleThreadScheduled(system_profiler_thread_scheduled* event)
|
||||
ModelLoader::_HandleThreadScheduled(uint32 cpu,
|
||||
system_profiler_thread_scheduled* event)
|
||||
{
|
||||
_UpdateLastEventTime(event->time);
|
||||
|
||||
@ -430,6 +467,8 @@ ModelLoader::_HandleThreadScheduled(system_profiler_thread_scheduled* event)
|
||||
// thread preempted
|
||||
thread->thread->AddPreemption(diffTime);
|
||||
thread->thread->AddRun(diffTime);
|
||||
if (thread->priority == 0)
|
||||
_AddIdleTime(cpu, diffTime);
|
||||
|
||||
thread->lastTime = fState.LastEventTime();
|
||||
thread->state = PREEMPTED;
|
||||
@ -437,6 +476,8 @@ ModelLoader::_HandleThreadScheduled(system_profiler_thread_scheduled* event)
|
||||
// thread starts waiting (it hadn't been added to the run
|
||||
// queue before being unscheduled)
|
||||
thread->thread->AddRun(diffTime);
|
||||
if (thread->priority == 0)
|
||||
_AddIdleTime(cpu, diffTime);
|
||||
|
||||
if (event->previous_thread_state == B_THREAD_WAITING) {
|
||||
addr_t waitObject = event->previous_thread_wait_object;
|
||||
@ -504,11 +545,13 @@ ModelLoader::_HandleThreadEnqueuedInRunQueue(
|
||||
thread->lastTime = fState.LastEventTime();
|
||||
thread->state = READY;
|
||||
}
|
||||
|
||||
thread->priority = event->priority;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ModelLoader::_HandleThreadRemovedFromRunQueue(
|
||||
ModelLoader::_HandleThreadRemovedFromRunQueue(uint32 cpu,
|
||||
thread_removed_from_run_queue* event)
|
||||
{
|
||||
_UpdateLastEventTime(event->time);
|
||||
@ -527,6 +570,8 @@ ModelLoader::_HandleThreadRemovedFromRunQueue(
|
||||
if (thread->state == RUNNING) {
|
||||
// This should never happen.
|
||||
thread->thread->AddRun(diffTime);
|
||||
if (thread->priority == 0)
|
||||
_AddIdleTime(cpu, diffTime);
|
||||
} else if (thread->state == READY || thread->state == PREEMPTED) {
|
||||
// Not really correct, but the case is rare and we keep it
|
||||
// simple.
|
||||
@ -566,6 +611,13 @@ ModelLoader::_AddThread(system_profiler_thread_added* event)
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
|
||||
// TODO: The priority is missing from the system_profiler_thread_added
|
||||
// struct. For now guess at least whether this is an idle thread.
|
||||
if (strncmp(event->name, "idle thread", strlen("idle thread")) == 0)
|
||||
info->priority = 0;
|
||||
else
|
||||
info->priority = B_NORMAL_PRIORITY;
|
||||
|
||||
fState.InsertThread(info);
|
||||
|
||||
return info;
|
||||
@ -601,3 +653,10 @@ printf("ModelLoader::_AddThreadWaitObject(): Unknown wait object: type: %lu, "
|
||||
|
||||
thread->waitObject = threadWaitObjectGroup->MostRecentThreadWaitObject();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ModelLoader::_AddIdleTime(uint32 cpu, nanotime_t time)
|
||||
{
|
||||
fCPUInfos[cpu].idleTime += time;
|
||||
}
|
||||
|
@ -40,6 +40,8 @@ private:
|
||||
typedef system_profiler_thread_removed_from_run_queue
|
||||
thread_removed_from_run_queue;
|
||||
|
||||
struct CPUInfo;
|
||||
|
||||
private:
|
||||
status_t _Load();
|
||||
status_t _ReadDebugEvents(void** _eventData,
|
||||
@ -59,11 +61,11 @@ private:
|
||||
system_profiler_thread_added* event);
|
||||
void _HandleThreadRemoved(
|
||||
system_profiler_thread_removed* event);
|
||||
void _HandleThreadScheduled(
|
||||
void _HandleThreadScheduled(uint32 cpu,
|
||||
system_profiler_thread_scheduled* event);
|
||||
void _HandleThreadEnqueuedInRunQueue(
|
||||
thread_enqueued_in_run_queue* event);
|
||||
void _HandleThreadRemovedFromRunQueue(
|
||||
void _HandleThreadRemovedFromRunQueue(uint32 cpu,
|
||||
thread_removed_from_run_queue* event);
|
||||
void _HandleWaitObjectInfo(
|
||||
system_profiler_wait_object_info* event);
|
||||
@ -73,11 +75,15 @@ private:
|
||||
void _AddThreadWaitObject(Model::ThreadSchedulingState* thread,
|
||||
uint32 type, addr_t object);
|
||||
|
||||
void _AddIdleTime(uint32 cpu, nanotime_t time);
|
||||
|
||||
private:
|
||||
Model* fModel;
|
||||
DataSource* fDataSource;
|
||||
CPUInfo* fCPUInfos;
|
||||
nanotime_t fBaseTime;
|
||||
Model::SchedulingState fState;
|
||||
uint32 fMaxCPUIndex;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user