1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 07:08:10 +00:00

Kernel+Profiler: Make profiling per-process and without core dumps

This patch merges the profiling functionality in the kernel with the
performance events mechanism. A profiler sample is now just another
perf event, rather than a dedicated thing.

Since perf events were already per-process, this now makes profiling
per-process as well.

Processes with perf events would already write out a perfcore.PID file
to the current directory on death, but since we may want to profile
a process and then let it continue running, recorded perf events can
now be accessed at any time via /proc/PID/perf_events.

This patch also adds information about process memory regions to the
perfcore JSON format. This removes the need to supply a core dump to
the Profiler app for symbolication, and so the "profiler coredump"
mechanism is removed entirely.

There's still a hard limit of 4MB worth of perf events per process,
so this is by no means a perfect final design, but it's a nice step
forward for both simplicity and stability.

Fixes #4848
Fixes #4849
This commit is contained in:
Andreas Kling 2021-01-11 09:52:18 +01:00
parent f259d96871
commit 5dafb72370
20 changed files with 195 additions and 310 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -597,16 +597,6 @@ void Process::finalize()
dbg() << "Finalizing process " << *this;
#endif
if (is_profiling()) {
auto coredump = CoreDump::create(*this, String::formatted("/tmp/profiler_coredumps/{}", pid().value()));
if (coredump) {
auto result = coredump->write();
if (result.is_error())
dbgln("Core dump generation failed: {}", result.error());
} else {
dbgln("Could not create coredump");
}
}
if (m_should_dump_core) {
dbgln("Generating coredump for pid: {}", m_pid.value());
@ -622,7 +612,7 @@ void Process::finalize()
}
if (m_perf_event_buffer) {
auto description_or_error = VFS::the().open(String::format("perfcore.%d", m_pid), O_CREAT | O_EXCL, 0400, current_directory(), UidAndGid { m_uid, m_gid });
auto description_or_error = VFS::the().open(String::formatted("perfcore.{}", m_pid), O_CREAT | O_EXCL, 0400, current_directory(), UidAndGid { m_uid, m_gid });
if (!description_or_error.is_error()) {
auto& description = description_or_error.value();
auto json = m_perf_event_buffer->to_json(m_pid, m_executable ? m_executable->absolute_path() : "");
@ -922,4 +912,11 @@ void Process::tracer_trap(Thread& thread, const RegisterState& regs)
thread.send_urgent_signal_to_self(SIGTRAP);
}
PerformanceEventBuffer& Process::ensure_perf_events()
{
if (!m_perf_event_buffer)
m_perf_event_buffer = make<PerformanceEventBuffer>();
return *m_perf_event_buffer;
}
}