diff options
author | Andreas Kling <kling@serenityos.org> | 2020-07-01 20:49:51 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-07-01 20:49:51 +0200 |
commit | 8d52e200ee56e05d638f51a081cd2a313f8aa443 (patch) | |
tree | 7d390d50799374143a33069caac69a275c741b47 /DevTools/Profiler/main.cpp | |
parent | c6193af26957b0fafdc67af5523c73a796613f6d (diff) | |
download | serenity-8d52e200ee56e05d638f51a081cd2a313f8aa443.zip |
Profiler: If run without arguments, let user select process from a list
We now show a list of running processes that the user can choose from.
After choosing one, we start profiling it and show a timer with a stop
button that the user has to press to stop profiling.
Diffstat (limited to 'DevTools/Profiler/main.cpp')
-rw-r--r-- | DevTools/Profiler/main.cpp | 112 |
1 files changed, 107 insertions, 5 deletions
diff --git a/DevTools/Profiler/main.cpp b/DevTools/Profiler/main.cpp index dc64030101..480d0116e0 100644 --- a/DevTools/Profiler/main.cpp +++ b/DevTools/Profiler/main.cpp @@ -26,26 +26,46 @@ #include "Profile.h" #include "ProfileTimelineWidget.h" +#include "RunningProcessesModel.h" +#include <LibCore/ElapsedTimer.h> +#include <LibCore/EventLoop.h> +#include <LibCore/Timer.h> #include <LibGUI/Action.h> #include <LibGUI/Application.h> #include <LibGUI/BoxLayout.h> +#include <LibGUI/Button.h> +#include <LibGUI/Desktop.h> +#include <LibGUI/Label.h> #include <LibGUI/Menu.h> #include <LibGUI/MenuBar.h> +#include <LibGUI/MessageBox.h> #include <LibGUI/Model.h> +#include <LibGUI/SortingProxyModel.h> #include <LibGUI/Splitter.h> #include <LibGUI/TableView.h> #include <LibGUI/TreeView.h> #include <LibGUI/Window.h> +#include <serenity.h> #include <stdio.h> +#include <string.h> + +static bool generate_profile(); int main(int argc, char** argv) { + GUI::Application app(argc, argv); + + const char* path = nullptr; if (argc != 2) { - printf("usage: %s <profile-file>\n", argv[0]); - return 0; + if (!generate_profile()) + return 0; + path = "/proc/profile"; + } else { + path = argv[1]; } - const char* path = argv[1]; + printf("We're here!\n"); + auto profile = Profile::load_from_perfcore_file(path); if (!profile) { @@ -53,8 +73,6 @@ int main(int argc, char** argv) return 1; } - GUI::Application app(argc, argv); - auto window = GUI::Window::construct(); window->set_title("Profiler"); window->set_rect(100, 100, 800, 600); @@ -102,3 +120,87 @@ int main(int argc, char** argv) window->show(); return app.exec(); } + +bool prompt_for_process_to_profile() +{ + bool success = false; + auto window = GUI::Window::construct(); + window->set_title("Profiler"); + Gfx::IntRect window_rect { 0, 0, 480, 360 }; + window_rect.center_within(GUI::Desktop::the().rect()); + window->set_rect(window_rect); + auto& widget = window->set_main_widget<GUI::Widget>(); + widget.set_fill_with_background_color(true); + widget.set_layout<GUI::VerticalBoxLayout>(); + auto& table_view = widget.add<GUI::TableView>(); + table_view.set_model(GUI::SortingProxyModel::create(Profiler::RunningProcessesModel::create())); + table_view.model()->set_key_column_and_sort_order(Profiler::RunningProcessesModel::Column::PID, GUI::SortOrder::Descending); + auto& button_container = widget.add<GUI::Widget>(); + button_container.set_preferred_size(0, 30); + button_container.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); + button_container.set_layout<GUI::HorizontalBoxLayout>(); + auto& profile_button = button_container.add<GUI::Button>("Profile"); + profile_button.on_click = [&](auto) { + if (table_view.selection().is_empty()) { + GUI::MessageBox::show("No process selected!", "Profiler", GUI::MessageBox::Type::Error, GUI::MessageBox::InputType::OK, window); + return; + } + auto index = table_view.selection().first(); + auto pid_as_variant = table_view.model()->data(index, GUI::Model::Role::Custom); + auto pid = pid_as_variant.as_i32(); + if (profiling_enable(pid) < 0) { + int saved_errno = errno; + GUI::MessageBox::show(String::format("Unable to profile PID %d: %s", pid, strerror(saved_errno)), "Profiler", GUI::MessageBox::Type::Error, GUI::MessageBox::InputType::OK, window); + return; + } + + success = true; + GUI::Application::the().quit(0); + }; + auto& cancel_button = button_container.add<GUI::Button>("Cancel"); + cancel_button.on_click = [](auto) { + GUI::Application::the().quit(1); + }; + + table_view.model()->update(); + window->show(); + return GUI::Application::the().exec() == 0; +} + +bool prompt_to_stop_profiling() +{ + auto window = GUI::Window::construct(); + window->set_title("Profiling"); + Gfx::IntRect window_rect { 0, 0, 320, 200 }; + window_rect.center_within(GUI::Desktop::the().rect()); + window->set_rect(window_rect); + auto& widget = window->set_main_widget<GUI::Widget>(); + widget.set_fill_with_background_color(true); + widget.set_layout<GUI::VerticalBoxLayout>(); + + auto& timer_label = widget.add<GUI::Label>("..."); + Core::ElapsedTimer clock; + clock.start(); + auto update_timer = Core::Timer::construct(100, [&] { + timer_label.set_text(String::format("%.1f seconds", (float)clock.elapsed() / 1000.0f)); + }); + + auto& stop_button = widget.add<GUI::Button>("Stop"); + stop_button.on_click = [&](auto) { + GUI::Application::the().quit(); + }; + + window->show(); + return GUI::Application::the().exec() == 0; +} + +bool generate_profile() +{ + if (!prompt_for_process_to_profile()) + return false; + + if (!prompt_to_stop_profiling()) + return false; + + return true; +} |