From a635ff4e600729fb7d12fdd16ac6ffbaa455bb30 Mon Sep 17 00:00:00 2001 From: Tom Date: Wed, 14 Jul 2021 21:46:32 -0600 Subject: Everywhere: Make tracking cpu usage independent from system ticks This switches tracking CPU usage to more accurately measure time in user and kernel land using either the TSC or another time source. This will also come in handy when implementing a tickless kernel mode. --- Userland/Applets/ResourceGraph/main.cpp | 8 +++--- .../Applications/SystemMonitor/ProcessModel.cpp | 32 +++++++++++----------- Userland/Applications/SystemMonitor/ProcessModel.h | 10 +++---- .../Libraries/LibCore/ProcessStatisticsReader.cpp | 9 +++--- .../Libraries/LibCore/ProcessStatisticsReader.h | 8 +++--- Userland/Utilities/top.cpp | 28 +++++++++---------- 6 files changed, 48 insertions(+), 47 deletions(-) (limited to 'Userland') diff --git a/Userland/Applets/ResourceGraph/main.cpp b/Userland/Applets/ResourceGraph/main.cpp index d9b5680858..45be04aafa 100644 --- a/Userland/Applets/ResourceGraph/main.cpp +++ b/Userland/Applets/ResourceGraph/main.cpp @@ -129,15 +129,15 @@ private: return false; if (m_last_total_sum.has_value()) - scheduled_diff = all_processes->total_ticks_scheduled - m_last_total_sum.value(); - m_last_total_sum = all_processes->total_ticks_scheduled; + scheduled_diff = all_processes->total_time_scheduled - m_last_total_sum.value(); + m_last_total_sum = all_processes->total_time_scheduled; for (auto& it : all_processes.value().processes) { for (auto& jt : it.threads) { if (it.pid == 0) - idle += jt.ticks_user + jt.ticks_kernel; + idle += jt.time_user + jt.time_kernel; else - busy += jt.ticks_user + jt.ticks_kernel; + busy += jt.time_user + jt.time_kernel; } } return true; diff --git a/Userland/Applications/SystemMonitor/ProcessModel.cpp b/Userland/Applications/SystemMonitor/ProcessModel.cpp index 5f91c24449..65364ce2a3 100644 --- a/Userland/Applications/SystemMonitor/ProcessModel.cpp +++ b/Userland/Applications/SystemMonitor/ProcessModel.cpp @@ -319,15 +319,15 @@ void ProcessModel::update() auto all_processes = Core::ProcessStatisticsReader::get_all(m_proc_all); HashTable live_tids; - u64 sum_ticks_scheduled = 0, sum_ticks_scheduled_kernel = 0; - u64 total_ticks_scheduled_diff = 0; + u64 sum_time_scheduled = 0, sum_time_scheduled_kernel = 0; + u64 total_time_scheduled_diff = 0; if (all_processes.has_value()) { - if (m_has_total_ticks) - total_ticks_scheduled_diff = all_processes->total_ticks_scheduled - m_total_ticks_scheduled; + if (m_has_total_scheduled_time) + total_time_scheduled_diff = all_processes->total_time_scheduled - m_total_time_scheduled; - m_total_ticks_scheduled = all_processes->total_ticks_scheduled; - m_total_ticks_scheduled_kernel = all_processes->total_ticks_scheduled_kernel; - m_has_total_ticks = true; + m_total_time_scheduled = all_processes->total_time_scheduled; + m_total_time_scheduled_kernel = all_processes->total_time_scheduled_kernel; + m_has_total_scheduled_time = true; for (auto& process : all_processes.value().processes) { for (auto& thread : process.threads) { @@ -361,14 +361,14 @@ void ProcessModel::update() state.tid = thread.tid; state.pgid = process.pgid; state.sid = process.sid; - state.ticks_user = thread.ticks_user; - state.ticks_kernel = thread.ticks_kernel; + state.time_user = thread.time_user; + state.time_kernel = thread.time_kernel; state.cpu = thread.cpu; state.cpu_percent = 0; state.priority = thread.priority; state.state = thread.state; - sum_ticks_scheduled += thread.ticks_user + thread.ticks_kernel; - sum_ticks_scheduled_kernel += thread.ticks_kernel; + sum_time_scheduled += thread.time_user + thread.time_kernel; + sum_time_scheduled_kernel += thread.time_kernel; { auto pit = m_threads.find(thread.tid); if (pit == m_threads.end()) @@ -397,11 +397,11 @@ void ProcessModel::update() continue; } auto& thread = *it.value; - u32 ticks_scheduled_diff = (thread.current_state.ticks_user + thread.current_state.ticks_kernel) - - (thread.previous_state.ticks_user + thread.previous_state.ticks_kernel); - u32 ticks_scheduled_diff_kernel = thread.current_state.ticks_kernel - thread.previous_state.ticks_kernel; - thread.current_state.cpu_percent = total_ticks_scheduled_diff > 0 ? ((float)ticks_scheduled_diff * 100) / (float)total_ticks_scheduled_diff : 0; - thread.current_state.cpu_percent_kernel = total_ticks_scheduled_diff > 0 ? ((float)ticks_scheduled_diff_kernel * 100) / (float)total_ticks_scheduled_diff : 0; + u32 time_scheduled_diff = (thread.current_state.time_user + thread.current_state.time_kernel) + - (thread.previous_state.time_user + thread.previous_state.time_kernel); + u32 time_scheduled_diff_kernel = thread.current_state.time_kernel - thread.previous_state.time_kernel; + thread.current_state.cpu_percent = total_time_scheduled_diff > 0 ? ((float)time_scheduled_diff * 100) / (float)total_time_scheduled_diff : 0; + thread.current_state.cpu_percent_kernel = total_time_scheduled_diff > 0 ? ((float)time_scheduled_diff_kernel * 100) / (float)total_time_scheduled_diff : 0; if (it.value->current_state.pid != 0) { auto& cpu_info = m_cpus[thread.current_state.cpu]; cpu_info.total_cpu_percent += thread.current_state.cpu_percent; diff --git a/Userland/Applications/SystemMonitor/ProcessModel.h b/Userland/Applications/SystemMonitor/ProcessModel.h index 13993ff257..c679e51d75 100644 --- a/Userland/Applications/SystemMonitor/ProcessModel.h +++ b/Userland/Applications/SystemMonitor/ProcessModel.h @@ -88,8 +88,8 @@ private: pid_t ppid; pid_t pgid; pid_t sid; - unsigned ticks_user; - unsigned ticks_kernel; + u64 time_user; + u64 time_kernel; bool kernel; String executable; String name; @@ -129,7 +129,7 @@ private: Vector m_tids; RefPtr m_proc_all; GUI::Icon m_kernel_process_icon; - u64 m_total_ticks_scheduled { 0 }; - u64 m_total_ticks_scheduled_kernel { 0 }; - bool m_has_total_ticks { false }; + u64 m_total_time_scheduled { 0 }; + u64 m_total_time_scheduled_kernel { 0 }; + bool m_has_total_scheduled_time { false }; }; diff --git a/Userland/Libraries/LibCore/ProcessStatisticsReader.cpp b/Userland/Libraries/LibCore/ProcessStatisticsReader.cpp index 9e0c652fe8..d17c88bbd6 100644 --- a/Userland/Libraries/LibCore/ProcessStatisticsReader.cpp +++ b/Userland/Libraries/LibCore/ProcessStatisticsReader.cpp @@ -37,6 +37,7 @@ Optional ProcessStatisticsReader::get_all(RefPtr ProcessStatisticsReader::get_all(RefPtr ProcessStatisticsReader::get_all(RefPtr processes; - u64 total_ticks_scheduled; - u64 total_ticks_scheduled_kernel; + u64 total_time_scheduled; + u64 total_time_scheduled_kernel; }; class ProcessStatisticsReader { diff --git a/Userland/Utilities/top.cpp b/Userland/Utilities/top.cpp index ec8bb07176..7e333eefaf 100644 --- a/Userland/Utilities/top.cpp +++ b/Userland/Utilities/top.cpp @@ -54,9 +54,9 @@ struct ThreadData { unsigned inode_faults; unsigned zero_faults; unsigned cow_faults; - u64 ticks_scheduled; + u64 time_scheduled; - u64 ticks_scheduled_since_prev { 0 }; + u64 time_scheduled_since_prev { 0 }; unsigned cpu_percent { 0 }; unsigned cpu_percent_decimal { 0 }; @@ -83,8 +83,8 @@ struct Traits : public GenericTraits { struct Snapshot { HashMap map; - u64 total_ticks_scheduled { 0 }; - u64 total_ticks_scheduled_kernel { 0 }; + u64 total_time_scheduled { 0 }; + u64 total_time_scheduled_kernel { 0 }; }; static Snapshot get_snapshot() @@ -115,7 +115,7 @@ static Snapshot get_snapshot() thread_data.inode_faults = thread.inode_faults; thread_data.zero_faults = thread.zero_faults; thread_data.cow_faults = thread.cow_faults; - thread_data.ticks_scheduled = (u64)thread.ticks_user + (u64)thread.ticks_kernel; + thread_data.time_scheduled = (u64)thread.time_user + (u64)thread.time_kernel; thread_data.priority = thread.priority; thread_data.state = thread.state; thread_data.username = process.username; @@ -124,8 +124,8 @@ static Snapshot get_snapshot() } } - snapshot.total_ticks_scheduled = all_processes->total_ticks_scheduled; - snapshot.total_ticks_scheduled_kernel = all_processes->total_ticks_scheduled_kernel; + snapshot.total_time_scheduled = all_processes->total_time_scheduled; + snapshot.total_time_scheduled_kernel = all_processes->total_time_scheduled_kernel; return snapshot; } @@ -220,7 +220,7 @@ int main(int argc, char** argv) } auto current = get_snapshot(); - auto total_scheduled_diff = current.total_ticks_scheduled - prev.total_ticks_scheduled; + auto total_scheduled_diff = current.total_time_scheduled - prev.total_time_scheduled; printf("\033[3J\033[H\033[2J"); printf("\033[47;30m%6s %3s %3s %-9s %-13s %6s %6s %4s %s\033[K\033[0m\n", @@ -240,11 +240,11 @@ int main(int argc, char** argv) auto jt = prev.map.find(pid_and_tid); if (jt == prev.map.end()) continue; - auto ticks_scheduled_before = (*jt).value.ticks_scheduled; - auto ticks_scheduled_diff = it.value.ticks_scheduled - ticks_scheduled_before; - it.value.ticks_scheduled_since_prev = ticks_scheduled_diff; - it.value.cpu_percent = total_scheduled_diff > 0 ? ((ticks_scheduled_diff * 100) / total_scheduled_diff) : 0; - it.value.cpu_percent_decimal = total_scheduled_diff > 0 ? (((ticks_scheduled_diff * 1000) / total_scheduled_diff) % 10) : 0; + auto time_scheduled_before = (*jt).value.time_scheduled; + auto time_scheduled_diff = it.value.time_scheduled - time_scheduled_before; + it.value.time_scheduled_since_prev = time_scheduled_diff; + it.value.cpu_percent = total_scheduled_diff > 0 ? ((time_scheduled_diff * 100) / total_scheduled_diff) : 0; + it.value.cpu_percent_decimal = total_scheduled_diff > 0 ? (((time_scheduled_diff * 1000) / total_scheduled_diff) % 10) : 0; threads.append(&it.value); } @@ -269,7 +269,7 @@ int main(int argc, char** argv) case TopOption::SortBy::Cpu: return p2->cpu_percent * 10 + p2->cpu_percent_decimal < p1->cpu_percent * 10 + p1->cpu_percent_decimal; default: - return p2->ticks_scheduled_since_prev < p1->ticks_scheduled_since_prev; + return p2->time_scheduled_since_prev < p1->time_scheduled_since_prev; } }); -- cgit v1.2.3