mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-25 05:55:13 +00:00
Ladybird+LibWebView: Add -P/--enable-callgrind-profiling option
This adds a -P option to run Ladybird under callgrind. It starts with instrumentation disabled. To start capturing a profile (once Ladybird has launched) run `callgrind_control -i on` and to stop it again run `callgrind_control -i off`. P.s. This is pretty much stolen from Andreas (and is based on the patch everyone [that wants a profile] have been manually applying).
This commit is contained in:
parent
5db1eb9961
commit
0329ddf46a
Notes:
sideshowbarker
2024-07-16 23:23:26 +09:00
Author: https://github.com/MacDue Commit: https://github.com/SerenityOS/serenity/commit/0329ddf46a Pull-request: https://github.com/SerenityOS/serenity/pull/18383
12 changed files with 52 additions and 26 deletions
|
@ -27,9 +27,11 @@
|
||||||
extern DeprecatedString s_serenity_resource_root;
|
extern DeprecatedString s_serenity_resource_root;
|
||||||
extern Browser::Settings* s_settings;
|
extern Browser::Settings* s_settings;
|
||||||
|
|
||||||
BrowserWindow::BrowserWindow(Browser::CookieJar& cookie_jar, StringView webdriver_content_ipc_path)
|
BrowserWindow::BrowserWindow(Browser::CookieJar& cookie_jar, StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling enable_callgrind_profiling)
|
||||||
: m_cookie_jar(cookie_jar)
|
: m_cookie_jar(cookie_jar)
|
||||||
, m_webdriver_content_ipc_path(webdriver_content_ipc_path)
|
, m_webdriver_content_ipc_path(webdriver_content_ipc_path)
|
||||||
|
, m_enable_callgrind_profiling(enable_callgrind_profiling)
|
||||||
|
|
||||||
{
|
{
|
||||||
m_tabs_container = new QTabWidget(this);
|
m_tabs_container = new QTabWidget(this);
|
||||||
m_tabs_container->installEventFilter(this);
|
m_tabs_container->installEventFilter(this);
|
||||||
|
@ -348,7 +350,7 @@ void BrowserWindow::debug_request(DeprecatedString const& request, DeprecatedStr
|
||||||
|
|
||||||
Tab& BrowserWindow::new_tab(QString const& url, Web::HTML::ActivateTab activate_tab)
|
Tab& BrowserWindow::new_tab(QString const& url, Web::HTML::ActivateTab activate_tab)
|
||||||
{
|
{
|
||||||
auto tab = make<Tab>(this, m_webdriver_content_ipc_path);
|
auto tab = make<Tab>(this, m_webdriver_content_ipc_path, m_enable_callgrind_profiling);
|
||||||
auto tab_ptr = tab.ptr();
|
auto tab_ptr = tab.ptr();
|
||||||
m_tabs.append(std::move(tab));
|
m_tabs.append(std::move(tab));
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ class CookieJar;
|
||||||
class BrowserWindow : public QMainWindow {
|
class BrowserWindow : public QMainWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit BrowserWindow(Browser::CookieJar&, StringView webdriver_content_ipc_path);
|
explicit BrowserWindow(Browser::CookieJar&, StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling);
|
||||||
|
|
||||||
WebContentView& view() const { return m_current_tab->view(); }
|
WebContentView& view() const { return m_current_tab->view(); }
|
||||||
|
|
||||||
|
@ -70,4 +70,5 @@ private:
|
||||||
Browser::CookieJar& m_cookie_jar;
|
Browser::CookieJar& m_cookie_jar;
|
||||||
|
|
||||||
StringView m_webdriver_content_ipc_path;
|
StringView m_webdriver_content_ipc_path;
|
||||||
|
WebView::EnableCallgrindProfiling m_enable_callgrind_profiling;
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
extern DeprecatedString s_serenity_resource_root;
|
extern DeprecatedString s_serenity_resource_root;
|
||||||
extern Browser::Settings* s_settings;
|
extern Browser::Settings* s_settings;
|
||||||
|
|
||||||
Tab::Tab(BrowserWindow* window, StringView webdriver_content_ipc_path)
|
Tab::Tab(BrowserWindow* window, StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling enable_callgrind_profiling)
|
||||||
: QWidget(window)
|
: QWidget(window)
|
||||||
, m_window(window)
|
, m_window(window)
|
||||||
{
|
{
|
||||||
|
@ -28,7 +28,7 @@ Tab::Tab(BrowserWindow* window, StringView webdriver_content_ipc_path)
|
||||||
m_layout->setSpacing(0);
|
m_layout->setSpacing(0);
|
||||||
m_layout->setContentsMargins(0, 0, 0, 0);
|
m_layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
m_view = new WebContentView(webdriver_content_ipc_path);
|
m_view = new WebContentView(webdriver_content_ipc_path, enable_callgrind_profiling);
|
||||||
m_toolbar = new QToolBar(this);
|
m_toolbar = new QToolBar(this);
|
||||||
m_location_edit = new LocationEdit(this);
|
m_location_edit = new LocationEdit(this);
|
||||||
m_reset_zoom_button = new QToolButton(m_toolbar);
|
m_reset_zoom_button = new QToolButton(m_toolbar);
|
||||||
|
|
|
@ -24,7 +24,7 @@ class BrowserWindow;
|
||||||
class Tab final : public QWidget {
|
class Tab final : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
Tab(BrowserWindow* window, StringView webdriver_content_ipc_path);
|
Tab(BrowserWindow* window, StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling);
|
||||||
|
|
||||||
WebContentView& view() { return *m_view; }
|
WebContentView& view() { return *m_view; }
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QToolTip>
|
#include <QToolTip>
|
||||||
|
|
||||||
WebContentView::WebContentView(StringView webdriver_content_ipc_path)
|
WebContentView::WebContentView(StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling enable_callgrind_profiling)
|
||||||
: m_webdriver_content_ipc_path(webdriver_content_ipc_path)
|
: m_webdriver_content_ipc_path(webdriver_content_ipc_path)
|
||||||
{
|
{
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
|
@ -76,7 +76,7 @@ WebContentView::WebContentView(StringView webdriver_content_ipc_path)
|
||||||
update_viewport_rect();
|
update_viewport_rect();
|
||||||
});
|
});
|
||||||
|
|
||||||
create_client();
|
create_client(enable_callgrind_profiling);
|
||||||
}
|
}
|
||||||
|
|
||||||
WebContentView::~WebContentView()
|
WebContentView::~WebContentView()
|
||||||
|
@ -599,12 +599,12 @@ void WebContentView::update_palette()
|
||||||
client().async_update_system_theme(make_system_theme_from_qt_palette(*this));
|
client().async_update_system_theme(make_system_theme_from_qt_palette(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebContentView::create_client()
|
void WebContentView::create_client(WebView::EnableCallgrindProfiling enable_callgrind_profiling)
|
||||||
{
|
{
|
||||||
m_client_state = {};
|
m_client_state = {};
|
||||||
|
|
||||||
auto candidate_web_content_paths = get_paths_for_helper_process("WebContent"sv).release_value_but_fixme_should_propagate_errors();
|
auto candidate_web_content_paths = get_paths_for_helper_process("WebContent"sv).release_value_but_fixme_should_propagate_errors();
|
||||||
auto new_client = launch_web_content_process(candidate_web_content_paths).release_value_but_fixme_should_propagate_errors();
|
auto new_client = launch_web_content_process(candidate_web_content_paths, enable_callgrind_profiling).release_value_but_fixme_should_propagate_errors();
|
||||||
|
|
||||||
m_web_content_notifier.setSocket(new_client->socket().fd().value());
|
m_web_content_notifier.setSocket(new_client->socket().fd().value());
|
||||||
m_web_content_notifier.setEnabled(true);
|
m_web_content_notifier.setEnabled(true);
|
||||||
|
|
|
@ -47,7 +47,7 @@ class WebContentView final
|
||||||
, public WebView::ViewImplementation {
|
, public WebView::ViewImplementation {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit WebContentView(StringView webdriver_content_ipc_path);
|
explicit WebContentView(StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling);
|
||||||
virtual ~WebContentView() override;
|
virtual ~WebContentView() override;
|
||||||
|
|
||||||
Function<String(Web::HTML::ActivateTab)> on_new_tab;
|
Function<String(Web::HTML::ActivateTab)> on_new_tab;
|
||||||
|
@ -185,7 +185,7 @@ signals:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ^WebView::ViewImplementation
|
// ^WebView::ViewImplementation
|
||||||
virtual void create_client() override;
|
virtual void create_client(WebView::EnableCallgrindProfiling = WebView::EnableCallgrindProfiling::No) override;
|
||||||
virtual void update_zoom() override;
|
virtual void update_zoom() override;
|
||||||
|
|
||||||
void request_repaint();
|
void request_repaint();
|
||||||
|
|
|
@ -67,11 +67,13 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
|
|
||||||
StringView raw_url;
|
StringView raw_url;
|
||||||
StringView webdriver_content_ipc_path;
|
StringView webdriver_content_ipc_path;
|
||||||
|
bool enable_callgrind_profiling = false;
|
||||||
|
|
||||||
Core::ArgsParser args_parser;
|
Core::ArgsParser args_parser;
|
||||||
args_parser.set_general_help("The Ladybird web browser :^)");
|
args_parser.set_general_help("The Ladybird web browser :^)");
|
||||||
args_parser.add_positional_argument(raw_url, "URL to open", "url", Core::ArgsParser::Required::No);
|
args_parser.add_positional_argument(raw_url, "URL to open", "url", Core::ArgsParser::Required::No);
|
||||||
args_parser.add_option(webdriver_content_ipc_path, "Path to WebDriver IPC for WebContent", "webdriver-content-path", 0, "path");
|
args_parser.add_option(webdriver_content_ipc_path, "Path to WebDriver IPC for WebContent", "webdriver-content-path", 0, "path");
|
||||||
|
args_parser.add_option(enable_callgrind_profiling, "Enable Callgrind profiling", "enable-callgrind-profiling", 'P');
|
||||||
args_parser.parse(arguments);
|
args_parser.parse(arguments);
|
||||||
|
|
||||||
auto get_formatted_url = [&](StringView const& raw_url) -> ErrorOr<URL> {
|
auto get_formatted_url = [&](StringView const& raw_url) -> ErrorOr<URL> {
|
||||||
|
@ -90,7 +92,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
auto cookie_jar = TRY(Browser::CookieJar::create(*database));
|
auto cookie_jar = TRY(Browser::CookieJar::create(*database));
|
||||||
|
|
||||||
s_settings = adopt_own_if_nonnull(new Browser::Settings());
|
s_settings = adopt_own_if_nonnull(new Browser::Settings());
|
||||||
BrowserWindow window(cookie_jar, webdriver_content_ipc_path);
|
BrowserWindow window(cookie_jar, webdriver_content_ipc_path, enable_callgrind_profiling ? WebView::EnableCallgrindProfiling::Yes : WebView::EnableCallgrindProfiling::No);
|
||||||
window.setWindowTitle("Ladybird");
|
window.setWindowTitle("Ladybird");
|
||||||
window.resize(800, 600);
|
window.resize(800, 600);
|
||||||
window.show();
|
window.show();
|
||||||
|
|
|
@ -59,7 +59,7 @@ void OutOfProcessWebView::handle_web_content_process_crash()
|
||||||
load_html(builder.to_deprecated_string(), m_url);
|
load_html(builder.to_deprecated_string(), m_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutOfProcessWebView::create_client()
|
void OutOfProcessWebView::create_client(EnableCallgrindProfiling)
|
||||||
{
|
{
|
||||||
m_client_state = {};
|
m_client_state = {};
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ private:
|
||||||
virtual void did_scroll() override;
|
virtual void did_scroll() override;
|
||||||
|
|
||||||
// ^WebView::ViewImplementation
|
// ^WebView::ViewImplementation
|
||||||
virtual void create_client() override;
|
virtual void create_client(EnableCallgrindProfiling = EnableCallgrindProfiling::No) override;
|
||||||
virtual void update_zoom() override;
|
virtual void update_zoom() override;
|
||||||
virtual void notify_server_did_layout(Badge<WebContentClient>, Gfx::IntSize content_size) override;
|
virtual void notify_server_did_layout(Badge<WebContentClient>, Gfx::IntSize content_size) override;
|
||||||
virtual void notify_server_did_paint(Badge<WebContentClient>, i32 bitmap_id) override;
|
virtual void notify_server_did_paint(Badge<WebContentClient>, i32 bitmap_id) override;
|
||||||
|
|
|
@ -126,7 +126,7 @@ void ViewImplementation::run_javascript(StringView js_source)
|
||||||
|
|
||||||
#if !defined(AK_OS_SERENITY)
|
#if !defined(AK_OS_SERENITY)
|
||||||
|
|
||||||
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> ViewImplementation::launch_web_content_process(ReadonlySpan<String> candidate_web_content_paths)
|
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> ViewImplementation::launch_web_content_process(ReadonlySpan<String> candidate_web_content_paths, EnableCallgrindProfiling enable_callgrind_profiling)
|
||||||
{
|
{
|
||||||
int socket_fds[2] {};
|
int socket_fds[2] {};
|
||||||
TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fds));
|
TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fds));
|
||||||
|
@ -149,15 +149,22 @@ ErrorOr<NonnullRefPtr<WebView::WebContentClient>> ViewImplementation::launch_web
|
||||||
|
|
||||||
auto webcontent_fd_passing_socket_string = TRY(String::number(wc_fd_passing_fd));
|
auto webcontent_fd_passing_socket_string = TRY(String::number(wc_fd_passing_fd));
|
||||||
|
|
||||||
auto arguments = Array {
|
ErrorOr<void> result;
|
||||||
"WebContent"sv,
|
for (auto const& path : candidate_web_content_paths) {
|
||||||
|
constexpr auto callgrind_prefix_length = 3;
|
||||||
|
auto arguments_with_callgrind_prefix = Array {
|
||||||
|
"valgrind"sv,
|
||||||
|
"--tool=callgrind"sv,
|
||||||
|
"--instr-atstart=no"sv,
|
||||||
|
path.bytes_as_string_view(),
|
||||||
"--webcontent-fd-passing-socket"sv,
|
"--webcontent-fd-passing-socket"sv,
|
||||||
webcontent_fd_passing_socket_string
|
webcontent_fd_passing_socket_string
|
||||||
};
|
};
|
||||||
|
auto arguments = arguments_with_callgrind_prefix.span();
|
||||||
|
if (enable_callgrind_profiling == EnableCallgrindProfiling::No)
|
||||||
|
arguments = arguments.slice(callgrind_prefix_length);
|
||||||
|
|
||||||
ErrorOr<void> result;
|
result = Core::System::exec(arguments[0], arguments, Core::System::SearchInPath::Yes);
|
||||||
for (auto const& path : candidate_web_content_paths) {
|
|
||||||
result = Core::System::exec(path, arguments, Core::System::SearchInPath::Yes);
|
|
||||||
if (!result.is_error())
|
if (!result.is_error())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -176,6 +183,13 @@ ErrorOr<NonnullRefPtr<WebView::WebContentClient>> ViewImplementation::launch_web
|
||||||
auto new_client = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) WebView::WebContentClient(move(socket), *this)));
|
auto new_client = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) WebView::WebContentClient(move(socket), *this)));
|
||||||
new_client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(ui_fd_passing_fd)));
|
new_client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(ui_fd_passing_fd)));
|
||||||
|
|
||||||
|
if (enable_callgrind_profiling == EnableCallgrindProfiling::Yes) {
|
||||||
|
dbgln();
|
||||||
|
dbgln("\033[1;45mLaunched WebContent process under callgrind!\033[0m");
|
||||||
|
dbgln("\033[100mRun `\033[4mcallgrind_control -i on\033[24m` to start instrumentation and `\033[4mcallgrind_control -i off\033[24m` stop it again.\033[0m");
|
||||||
|
dbgln();
|
||||||
|
}
|
||||||
|
|
||||||
return new_client;
|
return new_client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,12 @@
|
||||||
|
|
||||||
namespace WebView {
|
namespace WebView {
|
||||||
|
|
||||||
|
// Note: This only exists inside Serenity to avoid #ifdefs in all implementors of ViewImplementation.
|
||||||
|
enum class EnableCallgrindProfiling {
|
||||||
|
No,
|
||||||
|
Yes
|
||||||
|
};
|
||||||
|
|
||||||
class ViewImplementation {
|
class ViewImplementation {
|
||||||
public:
|
public:
|
||||||
virtual ~ViewImplementation() { }
|
virtual ~ViewImplementation() { }
|
||||||
|
@ -120,11 +126,12 @@ protected:
|
||||||
|
|
||||||
WebContentClient& client();
|
WebContentClient& client();
|
||||||
WebContentClient const& client() const;
|
WebContentClient const& client() const;
|
||||||
virtual void create_client() = 0;
|
|
||||||
virtual void update_zoom() = 0;
|
virtual void update_zoom() = 0;
|
||||||
|
|
||||||
|
virtual void create_client(EnableCallgrindProfiling = EnableCallgrindProfiling::No) {};
|
||||||
|
|
||||||
#if !defined(AK_OS_SERENITY)
|
#if !defined(AK_OS_SERENITY)
|
||||||
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(ReadonlySpan<String> candidate_web_content_paths);
|
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(ReadonlySpan<String> candidate_web_content_paths, EnableCallgrindProfiling = EnableCallgrindProfiling::No);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct SharedBitmap {
|
struct SharedBitmap {
|
||||||
|
|
|
@ -157,7 +157,7 @@ private:
|
||||||
|
|
||||||
void notify_server_did_finish_handling_input_event(bool) override { }
|
void notify_server_did_finish_handling_input_event(bool) override { }
|
||||||
void update_zoom() override { }
|
void update_zoom() override { }
|
||||||
void create_client() override { }
|
void create_client(WebView::EnableCallgrindProfiling) override { }
|
||||||
};
|
};
|
||||||
|
|
||||||
static ErrorOr<NonnullRefPtr<Core::Timer>> load_page_for_screenshot_and_exit(Core::EventLoop& event_loop, HeadlessWebContentView& view, int screenshot_timeout)
|
static ErrorOr<NonnullRefPtr<Core::Timer>> load_page_for_screenshot_and_exit(Core::EventLoop& event_loop, HeadlessWebContentView& view, int screenshot_timeout)
|
||||||
|
|
Loading…
Add table
Reference in a new issue