summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2021-07-14 21:46:32 -0600
committerAndreas Kling <kling@serenityos.org>2021-07-18 22:08:26 +0200
commita635ff4e600729fb7d12fdd16ac6ffbaa455bb30 (patch)
tree8625e110b4c9ca2510c3a8ac28b45bddae828af7 /Userland
parent7e77a2ec40bc339f41e75aa9fdc6744df449612c (diff)
downloadserenity-a635ff4e600729fb7d12fdd16ac6ffbaa455bb30.zip
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.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Applets/ResourceGraph/main.cpp8
-rw-r--r--Userland/Applications/SystemMonitor/ProcessModel.cpp32
-rw-r--r--Userland/Applications/SystemMonitor/ProcessModel.h10
-rw-r--r--Userland/Libraries/LibCore/ProcessStatisticsReader.cpp9
-rw-r--r--Userland/Libraries/LibCore/ProcessStatisticsReader.h8
-rw-r--r--Userland/Utilities/top.cpp28
6 files changed, 48 insertions, 47 deletions
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<int> 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<int> m_tids;
RefPtr<Core::File> 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<AllProcessesStatistics> ProcessStatisticsReader::get_all(RefPtr<Core::F
auto json = JsonValue::from_string(file_contents);
if (!json.has_value())
return {};
+
auto& json_obj = json.value().as_object();
json_obj.get("processes").as_array().for_each([&](auto& value) {
const JsonObject& process_object = value.as_object();
@@ -74,8 +75,8 @@ Optional<AllProcessesStatistics> ProcessStatisticsReader::get_all(RefPtr<Core::F
thread.times_scheduled = thread_object.get("times_scheduled").to_u32();
thread.name = thread_object.get("name").to_string();
thread.state = thread_object.get("state").to_string();
- thread.ticks_user = thread_object.get("ticks_user").to_u32();
- thread.ticks_kernel = thread_object.get("ticks_kernel").to_u32();
+ thread.time_user = thread_object.get("time_user").to_u64();
+ thread.time_kernel = thread_object.get("time_kernel").to_u64();
thread.cpu = thread_object.get("cpu").to_u32();
thread.priority = thread_object.get("priority").to_u32();
thread.syscall_count = thread_object.get("syscall_count").to_u32();
@@ -96,8 +97,8 @@ Optional<AllProcessesStatistics> ProcessStatisticsReader::get_all(RefPtr<Core::F
all_processes_statistics.processes.append(move(process));
});
- all_processes_statistics.total_ticks_scheduled = json_obj.get("total_ticks").to_u64();
- all_processes_statistics.total_ticks_scheduled_kernel = json_obj.get("total_ticks_kernel").to_u64();
+ all_processes_statistics.total_time_scheduled = json_obj.get("total_time").to_u64();
+ all_processes_statistics.total_time_scheduled_kernel = json_obj.get("total_time_kernel").to_u64();
return all_processes_statistics;
}
diff --git a/Userland/Libraries/LibCore/ProcessStatisticsReader.h b/Userland/Libraries/LibCore/ProcessStatisticsReader.h
index 2f4dc1e31f..19d541a948 100644
--- a/Userland/Libraries/LibCore/ProcessStatisticsReader.h
+++ b/Userland/Libraries/LibCore/ProcessStatisticsReader.h
@@ -15,8 +15,8 @@ namespace Core {
struct ThreadStatistics {
pid_t tid;
unsigned times_scheduled;
- unsigned ticks_user;
- unsigned ticks_kernel;
+ u64 time_user;
+ u64 time_kernel;
unsigned syscall_count;
unsigned inode_faults;
unsigned zero_faults;
@@ -66,8 +66,8 @@ struct ProcessStatistics {
struct AllProcessesStatistics {
Vector<ProcessStatistics> 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<PidAndTid> : public GenericTraits<PidAndTid> {
struct Snapshot {
HashMap<PidAndTid, ThreadData> 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;
}
});