diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-10-02 14:13:49 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-10-02 14:13:49 +0200 |
commit | 35138437efed0f37f303ba9c44d831a889871a29 (patch) | |
tree | 7bdd870ca191b86ffa1838a08ecf1b0175017100 | |
parent | c33ac7f1704fb26533a532e09ee9010c73077920 (diff) | |
download | serenity-35138437efed0f37f303ba9c44d831a889871a29.zip |
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.
-rw-r--r-- | Applications/SystemMonitor/ProcessModel.cpp | 27 | ||||
-rw-r--r-- | Applications/SystemMonitor/ProcessModel.h | 6 | ||||
-rw-r--r-- | Kernel/FileSystem/ProcFS.cpp | 3 | ||||
-rw-r--r-- | Kernel/Process.h | 9 | ||||
-rw-r--r-- | Kernel/VM/MemoryManager.cpp | 11 | ||||
-rw-r--r-- | Libraries/LibCore/CProcessStatisticsReader.cpp | 3 | ||||
-rw-r--r-- | Libraries/LibCore/CProcessStatisticsReader.h | 3 |
7 files changed, 62 insertions, 0 deletions
diff --git a/Applications/SystemMonitor/ProcessModel.cpp b/Applications/SystemMonitor/ProcessModel.cpp index b2f78245c8..32c96b3280 100644 --- a/Applications/SystemMonitor/ProcessModel.cpp +++ b/Applications/SystemMonitor/ProcessModel.cpp @@ -54,6 +54,12 @@ String ProcessModel::column_name(int column) const return "Name"; case Column::Syscalls: return "Syscalls"; + case Column::InodeFaults: + return "F:Inode"; + case Column::ZeroFaults: + return "F:Zero"; + case Column::CowFaults: + return "F:CoW"; default: ASSERT_NOT_REACHED(); } @@ -82,6 +88,12 @@ GModel::ColumnMetadata ProcessModel::column_metadata(int column) const return { 140, TextAlignment::CenterLeft }; case Column::Syscalls: 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: ASSERT_NOT_REACHED(); } @@ -131,6 +143,12 @@ GVariant ProcessModel::data(const GModelIndex& index, Role role) const // FIXME: GVariant with unsigned? case Column::Syscalls: 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(); 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? case Column::Syscalls: 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.priority = it.value.priority; 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.name = it.value.name; state.amount_virtual = it.value.amount_virtual; diff --git a/Applications/SystemMonitor/ProcessModel.h b/Applications/SystemMonitor/ProcessModel.h index 364a722bb8..21381f2fed 100644 --- a/Applications/SystemMonitor/ProcessModel.h +++ b/Applications/SystemMonitor/ProcessModel.h @@ -21,6 +21,9 @@ public: Virtual, Physical, Syscalls, + InodeFaults, + ZeroFaults, + CowFaults, __Count }; @@ -49,6 +52,9 @@ private: size_t amount_virtual; size_t amount_resident; unsigned syscall_count; + unsigned inode_faults; + unsigned zero_faults; + unsigned cow_faults; float cpu_percent; int icon_id; }; diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp index 397056866c..e523464914 100644 --- a/Kernel/FileSystem/ProcFS.cpp +++ b/Kernel/FileSystem/ProcFS.cpp @@ -685,6 +685,9 @@ Optional<KBuffer> procfs$all(InodeIdentifier) process_object.add("ticks", process.main_thread().ticks()); process_object.add("priority", to_string(process.priority())); 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()); }; build_process(*Scheduler::colonel()); diff --git a/Kernel/Process.h b/Kernel/Process.h index 52c20ae9e3..d01d87e084 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -291,6 +291,12 @@ public: unsigned syscall_count() const { return 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(); } @@ -369,6 +375,9 @@ private: int m_next_tid { 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; OwnPtr<ELFLoader> m_elf_loader; diff --git a/Kernel/VM/MemoryManager.cpp b/Kernel/VM/MemoryManager.cpp index 0e3cfcfc3d..16a008236f 100644 --- a/Kernel/VM/MemoryManager.cpp +++ b/Kernel/VM/MemoryManager.cpp @@ -296,6 +296,7 @@ bool MemoryManager::zero_page(Region& region, unsigned page_index_in_region) sti(); LOCKER(vmo.m_paging_lock); cli(); + if (!vmo_page.is_null()) { #ifdef PAGE_FAULT_DEBUG 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); return true; } + + if (current) + current->process().did_zero_fault(); + auto physical_page = allocate_user_physical_page(ShouldZeroFill::Yes); #ifdef PAGE_FAULT_DEBUG 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; } + if (current) + current->process().did_cow_fault(); + #ifdef PAGE_FAULT_DEBUG dbgprintf(" >> It's a COW page and it's time to COW!\n"); #endif @@ -367,6 +375,9 @@ bool MemoryManager::page_in_from_inode(Region& region, unsigned page_index_in_re return true; } + if (current) + current->process().did_inode_fault(); + #ifdef MM_DEBUG dbgprintf("MM: page_in_from_inode ready to read from inode\n"); #endif diff --git a/Libraries/LibCore/CProcessStatisticsReader.cpp b/Libraries/LibCore/CProcessStatisticsReader.cpp index aaf1fb7e04..1ccb72a9e3 100644 --- a/Libraries/LibCore/CProcessStatisticsReader.cpp +++ b/Libraries/LibCore/CProcessStatisticsReader.cpp @@ -43,6 +43,9 @@ HashMap<pid_t, CProcessStatistics> CProcessStatisticsReader::get_all() process.ticks = process_object.get("ticks").to_u32(); process.priority = process_object.get("priority").to_string(); 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(); // and synthetic data last diff --git a/Libraries/LibCore/CProcessStatisticsReader.h b/Libraries/LibCore/CProcessStatisticsReader.h index 55c513b779..c793d1f8f4 100644 --- a/Libraries/LibCore/CProcessStatisticsReader.h +++ b/Libraries/LibCore/CProcessStatisticsReader.h @@ -24,6 +24,9 @@ struct CProcessStatistics { unsigned ticks; String priority; unsigned syscall_count; + unsigned inode_faults; + unsigned zero_faults; + unsigned cow_faults; int icon_id; // synthetic |