summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-10-02 14:13:49 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-10-02 14:13:49 +0200
commit35138437efed0f37f303ba9c44d831a889871a29 (patch)
tree7bdd870ca191b86ffa1838a08ecf1b0175017100
parentc33ac7f1704fb26533a532e09ee9010c73077920 (diff)
downloadserenity-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.cpp27
-rw-r--r--Applications/SystemMonitor/ProcessModel.h6
-rw-r--r--Kernel/FileSystem/ProcFS.cpp3
-rw-r--r--Kernel/Process.h9
-rw-r--r--Kernel/VM/MemoryManager.cpp11
-rw-r--r--Libraries/LibCore/CProcessStatisticsReader.cpp3
-rw-r--r--Libraries/LibCore/CProcessStatisticsReader.h3
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