diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-12-01 17:36:06 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-12-01 17:40:27 +0100 |
commit | 5a45376180fe589622a169828bb030eb929a509d (patch) | |
tree | a47ff74abdda552b28e7cb661c7c839fac9061a5 | |
parent | a18aa8fd5f65708d840c5ff8c13f673ae4c8b079 (diff) | |
download | serenity-5a45376180fe589622a169828bb030eb929a509d.zip |
Kernel+SystemMonitor: Log amounts of I/O per thread
This patch adds these I/O counters to each thread:
- (Inode) file read bytes
- (Inode) file write bytes
- Unix socket read bytes
- Unix socket write bytes
- IPv4 socket read bytes
- IPv4 socket write bytes
These are then exposed in /proc/all and seen in SystemMonitor.
-rw-r--r-- | Applications/SystemMonitor/ProcessModel.cpp | 54 | ||||
-rw-r--r-- | Applications/SystemMonitor/ProcessModel.h | 12 | ||||
-rw-r--r-- | Kernel/FileSystem/InodeFile.cpp | 13 | ||||
-rw-r--r-- | Kernel/FileSystem/ProcFS.cpp | 6 | ||||
-rw-r--r-- | Kernel/Net/IPv4Socket.cpp | 10 | ||||
-rw-r--r-- | Kernel/Net/LocalSocket.cpp | 25 | ||||
-rw-r--r-- | Kernel/Net/LocalSocket.h | 3 | ||||
-rw-r--r-- | Kernel/Thread.h | 48 | ||||
-rw-r--r-- | Libraries/LibCore/CProcessStatisticsReader.cpp | 7 | ||||
-rw-r--r-- | Libraries/LibCore/CProcessStatisticsReader.h | 6 |
10 files changed, 169 insertions, 15 deletions
diff --git a/Applications/SystemMonitor/ProcessModel.cpp b/Applications/SystemMonitor/ProcessModel.cpp index 9dbaf99807..d6a6b782de 100644 --- a/Applications/SystemMonitor/ProcessModel.cpp +++ b/Applications/SystemMonitor/ProcessModel.cpp @@ -71,6 +71,18 @@ String ProcessModel::column_name(int column) const return "F:Zero"; case Column::CowFaults: return "F:CoW"; + case Column::IPv4SocketReadBytes: + return "IPv4 In"; + case Column::IPv4SocketWriteBytes: + return "IPv4 Out"; + case Column::UnixSocketReadBytes: + return "Unix In"; + case Column::UnixSocketWriteBytes: + return "Unix Out"; + case Column::FileReadBytes: + return "File In"; + case Column::FileWriteBytes: + return "File Out"; default: ASSERT_NOT_REACHED(); } @@ -107,6 +119,18 @@ GModel::ColumnMetadata ProcessModel::column_metadata(int column) const return { 60, TextAlignment::CenterRight }; case Column::CowFaults: return { 60, TextAlignment::CenterRight }; + case Column::FileReadBytes: + return { 60, TextAlignment::CenterRight }; + case Column::FileWriteBytes: + return { 60, TextAlignment::CenterRight }; + case Column::UnixSocketReadBytes: + return { 60, TextAlignment::CenterRight }; + case Column::UnixSocketWriteBytes: + return { 60, TextAlignment::CenterRight }; + case Column::IPv4SocketReadBytes: + return { 60, TextAlignment::CenterRight }; + case Column::IPv4SocketWriteBytes: + return { 60, TextAlignment::CenterRight }; default: ASSERT_NOT_REACHED(); } @@ -164,6 +188,18 @@ GVariant ProcessModel::data(const GModelIndex& index, Role role) const return (int)thread.current_state.zero_faults; case Column::CowFaults: return (int)thread.current_state.cow_faults; + case Column::IPv4SocketReadBytes: + return (int)thread.current_state.ipv4_socket_read_bytes; + case Column::IPv4SocketWriteBytes: + return (int)thread.current_state.ipv4_socket_write_bytes; + case Column::UnixSocketReadBytes: + return (int)thread.current_state.unix_socket_read_bytes; + case Column::UnixSocketWriteBytes: + return (int)thread.current_state.unix_socket_write_bytes; + case Column::FileReadBytes: + return (int)thread.current_state.file_read_bytes; + case Column::FileWriteBytes: + return (int)thread.current_state.file_write_bytes; } ASSERT_NOT_REACHED(); return {}; @@ -216,6 +252,18 @@ GVariant ProcessModel::data(const GModelIndex& index, Role role) const return (int)thread.current_state.zero_faults; case Column::CowFaults: return (int)thread.current_state.cow_faults; + case Column::IPv4SocketReadBytes: + return (int)thread.current_state.ipv4_socket_read_bytes; + case Column::IPv4SocketWriteBytes: + return (int)thread.current_state.ipv4_socket_write_bytes; + case Column::UnixSocketReadBytes: + return (int)thread.current_state.unix_socket_read_bytes; + case Column::UnixSocketWriteBytes: + return (int)thread.current_state.unix_socket_write_bytes; + case Column::FileReadBytes: + return (int)thread.current_state.file_read_bytes; + case Column::FileWriteBytes: + return (int)thread.current_state.file_write_bytes; } } @@ -241,6 +289,12 @@ void ProcessModel::update() state.inode_faults = thread.inode_faults; state.zero_faults = thread.zero_faults; state.cow_faults = thread.cow_faults; + state.unix_socket_read_bytes = thread.unix_socket_read_bytes; + state.unix_socket_write_bytes = thread.unix_socket_write_bytes; + state.ipv4_socket_read_bytes = thread.ipv4_socket_read_bytes; + state.ipv4_socket_write_bytes = thread.ipv4_socket_write_bytes; + state.file_read_bytes = thread.file_read_bytes; + state.file_write_bytes = thread.file_write_bytes; state.name = it.value.name; state.amount_virtual = it.value.amount_virtual; state.amount_resident = it.value.amount_resident; diff --git a/Applications/SystemMonitor/ProcessModel.h b/Applications/SystemMonitor/ProcessModel.h index c6365d109f..bb22d459cb 100644 --- a/Applications/SystemMonitor/ProcessModel.h +++ b/Applications/SystemMonitor/ProcessModel.h @@ -34,6 +34,12 @@ public: InodeFaults, ZeroFaults, CowFaults, + FileReadBytes, + FileWriteBytes, + UnixSocketReadBytes, + UnixSocketWriteBytes, + IPv4SocketReadBytes, + IPv4SocketWriteBytes, __Count }; @@ -68,6 +74,12 @@ private: unsigned inode_faults; unsigned zero_faults; unsigned cow_faults; + unsigned unix_socket_read_bytes; + unsigned unix_socket_write_bytes; + unsigned ipv4_socket_read_bytes; + unsigned ipv4_socket_write_bytes; + unsigned file_read_bytes; + unsigned file_write_bytes; float cpu_percent; int icon_id; }; diff --git a/Kernel/FileSystem/InodeFile.cpp b/Kernel/FileSystem/InodeFile.cpp index 7ba9814019..d47f42ba2a 100644 --- a/Kernel/FileSystem/InodeFile.cpp +++ b/Kernel/FileSystem/InodeFile.cpp @@ -15,15 +15,20 @@ InodeFile::~InodeFile() ssize_t InodeFile::read(FileDescription& description, u8* buffer, ssize_t count) { - return m_inode->read_bytes(description.offset(), count, buffer, &description); + ssize_t nread = m_inode->read_bytes(description.offset(), count, buffer, &description); + if (nread > 0) + current->did_file_read(nread); + return nread; } ssize_t InodeFile::write(FileDescription& description, const u8* data, ssize_t count) { - ssize_t ret = m_inode->write_bytes(description.offset(), count, data, &description); - if (ret > 0) + ssize_t nwritten = m_inode->write_bytes(description.offset(), count, data, &description); + if (nwritten > 0) { m_inode->set_mtime(kgettimeofday().tv_sec); - return ret; + current->did_file_write(nwritten); + } + return nwritten; } KResultOr<Region*> InodeFile::mmap(Process& process, FileDescription& description, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot) diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp index 2f98ae442b..749a169538 100644 --- a/Kernel/FileSystem/ProcFS.cpp +++ b/Kernel/FileSystem/ProcFS.cpp @@ -725,6 +725,12 @@ Optional<KBuffer> procfs$all(InodeIdentifier) thread_object.add("inode_faults", thread.inode_faults()); thread_object.add("zero_faults", thread.zero_faults()); thread_object.add("cow_faults", thread.cow_faults()); + thread_object.add("file_read_bytes", thread.file_read_bytes()); + thread_object.add("file_write_bytes", thread.file_write_bytes()); + thread_object.add("unix_socket_read_bytes", thread.unix_socket_read_bytes()); + thread_object.add("unix_socket_write_bytes", thread.unix_socket_write_bytes()); + thread_object.add("ipv4_socket_read_bytes", thread.ipv4_socket_read_bytes()); + thread_object.add("ipv4_socket_write_bytes", thread.ipv4_socket_write_bytes()); return IterationDecision::Continue; }); }; diff --git a/Kernel/Net/IPv4Socket.cpp b/Kernel/Net/IPv4Socket.cpp index 3949fb5692..06d3e21249 100644 --- a/Kernel/Net/IPv4Socket.cpp +++ b/Kernel/Net/IPv4Socket.cpp @@ -206,7 +206,10 @@ ssize_t IPv4Socket::sendto(FileDescription&, const void* data, size_t data_lengt return data_length; } - return protocol_send(data, data_length); + int nsent = protocol_send(data, data_length); + if (nsent > 0) + current->did_ipv4_socket_write(nsent); + return nsent; } ssize_t IPv4Socket::recvfrom(FileDescription& description, void* buffer, size_t buffer_length, int flags, sockaddr* addr, socklen_t* addr_length) @@ -285,7 +288,10 @@ ssize_t IPv4Socket::recvfrom(FileDescription& description, void* buffer, size_t return ipv4_packet.payload_size(); } - return protocol_receive(packet.data.value(), buffer, buffer_length, flags); + int nreceived = protocol_receive(packet.data.value(), buffer, buffer_length, flags); + if (nreceived > 0) + current->did_ipv4_socket_read(nreceived); + return nreceived; } bool IPv4Socket::did_receive(const IPv4Address& source_address, u16 source_port, KBuffer&& packet) diff --git a/Kernel/Net/LocalSocket.cpp b/Kernel/Net/LocalSocket.cpp index babe57a023..d41d445620 100644 --- a/Kernel/Net/LocalSocket.cpp +++ b/Kernel/Net/LocalSocket.cpp @@ -222,27 +222,35 @@ ssize_t LocalSocket::sendto(FileDescription& description, const void* data, size { if (!has_attached_peer(description)) return -EPIPE; + ssize_t nwritten = send_buffer_for(description).write((const u8*)data, data_size); + if (nwritten > 0) + current->did_unix_socket_write(nwritten); + return nwritten; +} + +DoubleBuffer& LocalSocket::receive_buffer_for(FileDescription& description) +{ auto role = this->role(description); if (role == Role::Accepted) - return m_for_client.write((const u8*)data, data_size); + return m_for_server; if (role == Role::Connected) - return m_for_server.write((const u8*)data, data_size); + return m_for_client; ASSERT_NOT_REACHED(); } -DoubleBuffer& LocalSocket::buffer_for(FileDescription& description) +DoubleBuffer& LocalSocket::send_buffer_for(FileDescription& description) { auto role = this->role(description); - if (role == Role::Accepted) - return m_for_server; if (role == Role::Connected) + return m_for_server; + if (role == Role::Accepted) return m_for_client; ASSERT_NOT_REACHED(); } ssize_t LocalSocket::recvfrom(FileDescription& description, void* buffer, size_t buffer_size, int, sockaddr*, socklen_t*) { - auto& buffer_for_me = buffer_for(description); + auto& buffer_for_me = receive_buffer_for(description); if (!description.is_blocking()) { if (buffer_for_me.is_empty()) { if (!has_attached_peer(description)) @@ -257,7 +265,10 @@ ssize_t LocalSocket::recvfrom(FileDescription& description, void* buffer, size_t if (!has_attached_peer(description) && buffer_for_me.is_empty()) return 0; ASSERT(!buffer_for_me.is_empty()); - return buffer_for_me.read((u8*)buffer, buffer_size); + int nread = buffer_for_me.read((u8*)buffer, buffer_size); + if (nread > 0) + current->did_unix_socket_read(nread); + return nread; } StringView LocalSocket::socket_path() const diff --git a/Kernel/Net/LocalSocket.h b/Kernel/Net/LocalSocket.h index bd529933f1..7677a25e8d 100644 --- a/Kernel/Net/LocalSocket.h +++ b/Kernel/Net/LocalSocket.h @@ -36,7 +36,8 @@ private: virtual bool is_local() const override { return true; } bool has_attached_peer(const FileDescription&) const; static Lockable<InlineLinkedList<LocalSocket>>& all_sockets(); - DoubleBuffer& buffer_for(FileDescription&); + DoubleBuffer& receive_buffer_for(FileDescription&); + DoubleBuffer& send_buffer_for(FileDescription&); // An open socket file on the filesystem. RefPtr<FileDescription> m_file; diff --git a/Kernel/Thread.h b/Kernel/Thread.h index 54a46e4e2d..8f3c044438 100644 --- a/Kernel/Thread.h +++ b/Kernel/Thread.h @@ -363,6 +363,45 @@ public: unsigned cow_faults() const { return m_cow_faults; } void did_cow_fault() { ++m_cow_faults; } + unsigned file_read_bytes() const { return m_file_read_bytes; } + unsigned file_write_bytes() const { return m_file_write_bytes; } + + void did_file_read(unsigned bytes) + { + m_file_read_bytes += bytes; + } + + void did_file_write(unsigned bytes) + { + m_file_write_bytes += bytes; + } + + unsigned unix_socket_read_bytes() const { return m_unix_socket_read_bytes; } + unsigned unix_socket_write_bytes() const { return m_unix_socket_write_bytes; } + + void did_unix_socket_read(unsigned bytes) + { + m_unix_socket_read_bytes += bytes; + } + + void did_unix_socket_write(unsigned bytes) + { + m_unix_socket_write_bytes += bytes; + } + + unsigned ipv4_socket_read_bytes() const { return m_ipv4_socket_read_bytes; } + unsigned ipv4_socket_write_bytes() const { return m_ipv4_socket_write_bytes; } + + void did_ipv4_socket_read(unsigned bytes) + { + m_ipv4_socket_read_bytes += bytes; + } + + void did_ipv4_socket_write(unsigned bytes) + { + m_ipv4_socket_write_bytes += bytes; + } + Thread* clone(Process&); template<typename Callback> @@ -416,6 +455,15 @@ private: unsigned m_zero_faults { 0 }; unsigned m_cow_faults { 0 }; + unsigned m_file_read_bytes { 0 }; + unsigned m_file_write_bytes { 0 }; + + unsigned m_unix_socket_read_bytes { 0 }; + unsigned m_unix_socket_write_bytes { 0 }; + + unsigned m_ipv4_socket_read_bytes { 0 }; + unsigned m_ipv4_socket_write_bytes { 0 }; + FPUState* m_fpu_state { nullptr }; State m_state { Invalid }; ThreadPriority m_priority { ThreadPriority::Normal }; diff --git a/Libraries/LibCore/CProcessStatisticsReader.cpp b/Libraries/LibCore/CProcessStatisticsReader.cpp index 39f8db097e..39db980ee8 100644 --- a/Libraries/LibCore/CProcessStatisticsReader.cpp +++ b/Libraries/LibCore/CProcessStatisticsReader.cpp @@ -53,6 +53,12 @@ HashMap<pid_t, CProcessStatistics> CProcessStatisticsReader::get_all() thread.inode_faults = thread_object.get("inode_faults").to_u32(); thread.zero_faults = thread_object.get("zero_faults").to_u32(); thread.cow_faults = thread_object.get("cow_faults").to_u32(); + thread.unix_socket_read_bytes = thread_object.get("unix_socket_read_bytes").to_u32(); + thread.unix_socket_write_bytes = thread_object.get("unix_socket_write_bytes").to_u32(); + thread.ipv4_socket_read_bytes = thread_object.get("ipv4_socket_read_bytes").to_u32(); + thread.ipv4_socket_write_bytes = thread_object.get("ipv4_socket_write_bytes").to_u32(); + thread.file_read_bytes = thread_object.get("file_read_bytes").to_u32(); + thread.file_write_bytes = thread_object.get("file_write_bytes").to_u32(); process.threads.append(move(thread)); }); @@ -78,4 +84,3 @@ String CProcessStatisticsReader::username_from_uid(uid_t uid) return (*it).value; return String::number(uid); } - diff --git a/Libraries/LibCore/CProcessStatisticsReader.h b/Libraries/LibCore/CProcessStatisticsReader.h index bb6da21d31..05e9e9659e 100644 --- a/Libraries/LibCore/CProcessStatisticsReader.h +++ b/Libraries/LibCore/CProcessStatisticsReader.h @@ -12,6 +12,12 @@ struct CThreadStatistics { unsigned inode_faults; unsigned zero_faults; unsigned cow_faults; + unsigned unix_socket_read_bytes; + unsigned unix_socket_write_bytes; + unsigned ipv4_socket_read_bytes; + unsigned ipv4_socket_write_bytes; + unsigned file_read_bytes; + unsigned file_write_bytes; String state; String priority; }; |