mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 08:58:11 +00:00
Kernel+SystemMonitor: Add fault counters
This patch adds three separate per-process fault counters: - Inode faults An inode fault happens when we've memory-mapped a file from disk and we end up having to load 1 page (4KB) of the file into memory. - Zero faults Memory returned by mmap() is lazily zeroed out. Every time we have to zero out 1 page, we count a zero fault. - CoW faults VM objects can be shared by multiple mappings that make their own unique copy iff they want to modify it. The typical reason here is memory shared between a parent and child process.
This commit is contained in:
parent
c33ac7f170
commit
35138437ef
7 changed files with 62 additions and 0 deletions
|
@ -54,6 +54,12 @@ String ProcessModel::column_name(int column) const
|
||||||
return "Name";
|
return "Name";
|
||||||
case Column::Syscalls:
|
case Column::Syscalls:
|
||||||
return "Syscalls";
|
return "Syscalls";
|
||||||
|
case Column::InodeFaults:
|
||||||
|
return "F:Inode";
|
||||||
|
case Column::ZeroFaults:
|
||||||
|
return "F:Zero";
|
||||||
|
case Column::CowFaults:
|
||||||
|
return "F:CoW";
|
||||||
default:
|
default:
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -82,6 +88,12 @@ GModel::ColumnMetadata ProcessModel::column_metadata(int column) const
|
||||||
return { 140, TextAlignment::CenterLeft };
|
return { 140, TextAlignment::CenterLeft };
|
||||||
case Column::Syscalls:
|
case Column::Syscalls:
|
||||||
return { 60, TextAlignment::CenterRight };
|
return { 60, TextAlignment::CenterRight };
|
||||||
|
case Column::InodeFaults:
|
||||||
|
return { 60, TextAlignment::CenterRight };
|
||||||
|
case Column::ZeroFaults:
|
||||||
|
return { 60, TextAlignment::CenterRight };
|
||||||
|
case Column::CowFaults:
|
||||||
|
return { 60, TextAlignment::CenterRight };
|
||||||
default:
|
default:
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -131,6 +143,12 @@ GVariant ProcessModel::data(const GModelIndex& index, Role role) const
|
||||||
// FIXME: GVariant with unsigned?
|
// FIXME: GVariant with unsigned?
|
||||||
case Column::Syscalls:
|
case Column::Syscalls:
|
||||||
return (int)process.current_state.syscall_count;
|
return (int)process.current_state.syscall_count;
|
||||||
|
case Column::InodeFaults:
|
||||||
|
return (int)process.current_state.inode_faults;
|
||||||
|
case Column::ZeroFaults:
|
||||||
|
return (int)process.current_state.zero_faults;
|
||||||
|
case Column::CowFaults:
|
||||||
|
return (int)process.current_state.cow_faults;
|
||||||
}
|
}
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
return {};
|
return {};
|
||||||
|
@ -175,6 +193,12 @@ GVariant ProcessModel::data(const GModelIndex& index, Role role) const
|
||||||
// FIXME: It's weird that GVariant doesn't support unsigned ints. Should it?
|
// FIXME: It's weird that GVariant doesn't support unsigned ints. Should it?
|
||||||
case Column::Syscalls:
|
case Column::Syscalls:
|
||||||
return (int)process.current_state.syscall_count;
|
return (int)process.current_state.syscall_count;
|
||||||
|
case Column::InodeFaults:
|
||||||
|
return (int)process.current_state.inode_faults;
|
||||||
|
case Column::ZeroFaults:
|
||||||
|
return (int)process.current_state.zero_faults;
|
||||||
|
case Column::CowFaults:
|
||||||
|
return (int)process.current_state.cow_faults;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,6 +222,9 @@ void ProcessModel::update()
|
||||||
state.user = it.value.username;
|
state.user = it.value.username;
|
||||||
state.priority = it.value.priority;
|
state.priority = it.value.priority;
|
||||||
state.syscall_count = it.value.syscall_count;
|
state.syscall_count = it.value.syscall_count;
|
||||||
|
state.inode_faults = it.value.inode_faults;
|
||||||
|
state.zero_faults = it.value.zero_faults;
|
||||||
|
state.cow_faults = it.value.cow_faults;
|
||||||
state.state = it.value.state;
|
state.state = it.value.state;
|
||||||
state.name = it.value.name;
|
state.name = it.value.name;
|
||||||
state.amount_virtual = it.value.amount_virtual;
|
state.amount_virtual = it.value.amount_virtual;
|
||||||
|
|
|
@ -21,6 +21,9 @@ public:
|
||||||
Virtual,
|
Virtual,
|
||||||
Physical,
|
Physical,
|
||||||
Syscalls,
|
Syscalls,
|
||||||
|
InodeFaults,
|
||||||
|
ZeroFaults,
|
||||||
|
CowFaults,
|
||||||
__Count
|
__Count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -49,6 +52,9 @@ private:
|
||||||
size_t amount_virtual;
|
size_t amount_virtual;
|
||||||
size_t amount_resident;
|
size_t amount_resident;
|
||||||
unsigned syscall_count;
|
unsigned syscall_count;
|
||||||
|
unsigned inode_faults;
|
||||||
|
unsigned zero_faults;
|
||||||
|
unsigned cow_faults;
|
||||||
float cpu_percent;
|
float cpu_percent;
|
||||||
int icon_id;
|
int icon_id;
|
||||||
};
|
};
|
||||||
|
|
|
@ -685,6 +685,9 @@ Optional<KBuffer> procfs$all(InodeIdentifier)
|
||||||
process_object.add("ticks", process.main_thread().ticks());
|
process_object.add("ticks", process.main_thread().ticks());
|
||||||
process_object.add("priority", to_string(process.priority()));
|
process_object.add("priority", to_string(process.priority()));
|
||||||
process_object.add("syscall_count", process.syscall_count());
|
process_object.add("syscall_count", process.syscall_count());
|
||||||
|
process_object.add("inode_faults", process.inode_faults());
|
||||||
|
process_object.add("zero_faults", process.zero_faults());
|
||||||
|
process_object.add("cow_faults", process.cow_faults());
|
||||||
process_object.add("icon_id", process.icon_id());
|
process_object.add("icon_id", process.icon_id());
|
||||||
};
|
};
|
||||||
build_process(*Scheduler::colonel());
|
build_process(*Scheduler::colonel());
|
||||||
|
|
|
@ -291,6 +291,12 @@ public:
|
||||||
|
|
||||||
unsigned syscall_count() const { return m_syscall_count; }
|
unsigned syscall_count() const { return m_syscall_count; }
|
||||||
void did_syscall() { ++m_syscall_count; }
|
void did_syscall() { ++m_syscall_count; }
|
||||||
|
unsigned inode_faults() const { return m_inode_faults; }
|
||||||
|
void did_inode_fault() { ++m_inode_faults; }
|
||||||
|
unsigned zero_faults() const { return m_zero_faults; }
|
||||||
|
void did_zero_fault() { ++m_zero_faults; }
|
||||||
|
unsigned cow_faults() const { return m_cow_faults; }
|
||||||
|
void did_cow_fault() { ++m_cow_faults; }
|
||||||
|
|
||||||
const ELFLoader* elf_loader() const { return m_elf_loader.ptr(); }
|
const ELFLoader* elf_loader() const { return m_elf_loader.ptr(); }
|
||||||
|
|
||||||
|
@ -369,6 +375,9 @@ private:
|
||||||
int m_next_tid { 0 };
|
int m_next_tid { 0 };
|
||||||
|
|
||||||
unsigned m_syscall_count { 0 };
|
unsigned m_syscall_count { 0 };
|
||||||
|
unsigned m_inode_faults { 0 };
|
||||||
|
unsigned m_zero_faults { 0 };
|
||||||
|
unsigned m_cow_faults { 0 };
|
||||||
|
|
||||||
RefPtr<ProcessTracer> m_tracer;
|
RefPtr<ProcessTracer> m_tracer;
|
||||||
OwnPtr<ELFLoader> m_elf_loader;
|
OwnPtr<ELFLoader> m_elf_loader;
|
||||||
|
|
|
@ -296,6 +296,7 @@ bool MemoryManager::zero_page(Region& region, unsigned page_index_in_region)
|
||||||
sti();
|
sti();
|
||||||
LOCKER(vmo.m_paging_lock);
|
LOCKER(vmo.m_paging_lock);
|
||||||
cli();
|
cli();
|
||||||
|
|
||||||
if (!vmo_page.is_null()) {
|
if (!vmo_page.is_null()) {
|
||||||
#ifdef PAGE_FAULT_DEBUG
|
#ifdef PAGE_FAULT_DEBUG
|
||||||
dbgprintf("MM: zero_page() but page already present. Fine with me!\n");
|
dbgprintf("MM: zero_page() but page already present. Fine with me!\n");
|
||||||
|
@ -303,6 +304,10 @@ bool MemoryManager::zero_page(Region& region, unsigned page_index_in_region)
|
||||||
remap_region_page(region, page_index_in_region);
|
remap_region_page(region, page_index_in_region);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (current)
|
||||||
|
current->process().did_zero_fault();
|
||||||
|
|
||||||
auto physical_page = allocate_user_physical_page(ShouldZeroFill::Yes);
|
auto physical_page = allocate_user_physical_page(ShouldZeroFill::Yes);
|
||||||
#ifdef PAGE_FAULT_DEBUG
|
#ifdef PAGE_FAULT_DEBUG
|
||||||
dbgprintf(" >> ZERO P%p\n", physical_page->paddr().get());
|
dbgprintf(" >> ZERO P%p\n", physical_page->paddr().get());
|
||||||
|
@ -325,6 +330,9 @@ bool MemoryManager::copy_on_write(Region& region, unsigned page_index_in_region)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (current)
|
||||||
|
current->process().did_cow_fault();
|
||||||
|
|
||||||
#ifdef PAGE_FAULT_DEBUG
|
#ifdef PAGE_FAULT_DEBUG
|
||||||
dbgprintf(" >> It's a COW page and it's time to COW!\n");
|
dbgprintf(" >> It's a COW page and it's time to COW!\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -367,6 +375,9 @@ bool MemoryManager::page_in_from_inode(Region& region, unsigned page_index_in_re
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (current)
|
||||||
|
current->process().did_inode_fault();
|
||||||
|
|
||||||
#ifdef MM_DEBUG
|
#ifdef MM_DEBUG
|
||||||
dbgprintf("MM: page_in_from_inode ready to read from inode\n");
|
dbgprintf("MM: page_in_from_inode ready to read from inode\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -43,6 +43,9 @@ HashMap<pid_t, CProcessStatistics> CProcessStatisticsReader::get_all()
|
||||||
process.ticks = process_object.get("ticks").to_u32();
|
process.ticks = process_object.get("ticks").to_u32();
|
||||||
process.priority = process_object.get("priority").to_string();
|
process.priority = process_object.get("priority").to_string();
|
||||||
process.syscall_count = process_object.get("syscall_count").to_u32();
|
process.syscall_count = process_object.get("syscall_count").to_u32();
|
||||||
|
process.inode_faults = process_object.get("inode_faults").to_u32();
|
||||||
|
process.zero_faults = process_object.get("zero_faults").to_u32();
|
||||||
|
process.cow_faults = process_object.get("cow_faults").to_u32();
|
||||||
process.icon_id = process_object.get("icon_id").to_int();
|
process.icon_id = process_object.get("icon_id").to_int();
|
||||||
|
|
||||||
// and synthetic data last
|
// and synthetic data last
|
||||||
|
|
|
@ -24,6 +24,9 @@ struct CProcessStatistics {
|
||||||
unsigned ticks;
|
unsigned ticks;
|
||||||
String priority;
|
String priority;
|
||||||
unsigned syscall_count;
|
unsigned syscall_count;
|
||||||
|
unsigned inode_faults;
|
||||||
|
unsigned zero_faults;
|
||||||
|
unsigned cow_faults;
|
||||||
int icon_id;
|
int icon_id;
|
||||||
|
|
||||||
// synthetic
|
// synthetic
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue