From efa8e26a3f3f7ba5e536cd10e86303b4fe1baba0 Mon Sep 17 00:00:00 2001 From: Jan Dalheimer Date: Sat, 15 Feb 2014 14:19:35 +0100 Subject: Profiler support. Currently JProfiler and JVisualVM are implemented. --- gui/MainWindow.cpp | 56 ++++++++++++++++++--- gui/MainWindow.h | 8 +-- gui/MainWindow.ui | 12 ++++- gui/dialogs/SettingsDialog.cpp | 85 +++++++++++++++++++++++++++++++ gui/dialogs/SettingsDialog.h | 5 ++ gui/dialogs/SettingsDialog.ui | 112 ++++++++++++++++++++++++++++++++++++++++- 6 files changed, 264 insertions(+), 14 deletions(-) (limited to 'gui') diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index 29f7c8e8..ddeb9947 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include "osutils.h" #include "userutils.h" @@ -97,6 +98,9 @@ #include #include +#include "logic/profiler/BaseProfiler.h" +#include "logic/OneSixInstance.h" + MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { MultiMCPlatform::fixWM_CLASS(this); @@ -1078,7 +1082,7 @@ void MainWindow::on_actionLaunchInstanceOffline_triggered() } } -void MainWindow::doLaunch(bool online) +void MainWindow::doLaunch(bool online, bool profile) { if (!m_selectedInstance) return; @@ -1194,11 +1198,11 @@ void MainWindow::doLaunch(bool online) // update first if the server actually responded if (session->auth_server_online) { - updateInstance(m_selectedInstance, session); + updateInstance(m_selectedInstance, session, profile); } else { - launchInstance(m_selectedInstance, session); + launchInstance(m_selectedInstance, session, profile); } tryagain = false; } @@ -1206,22 +1210,22 @@ void MainWindow::doLaunch(bool online) } } -void MainWindow::updateInstance(BaseInstance *instance, AuthSessionPtr session) +void MainWindow::updateInstance(BaseInstance *instance, AuthSessionPtr session, bool profile) { auto updateTask = instance->doUpdate(); if (!updateTask) { - launchInstance(instance, session); + launchInstance(instance, session, profile); return; } ProgressDialog tDialog(this); - connect(updateTask.get(), &Task::succeeded, [this, instance, session] - { launchInstance(instance, session); }); + connect(updateTask.get(), &Task::succeeded, [this, instance, session, profile] + { launchInstance(instance, session, profile); }); connect(updateTask.get(), SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString))); tDialog.exec(updateTask.get()); } -void MainWindow::launchInstance(BaseInstance *instance, AuthSessionPtr session) +void MainWindow::launchInstance(BaseInstance *instance, AuthSessionPtr session, bool profile) { Q_ASSERT_X(instance != NULL, "launchInstance", "instance is NULL"); Q_ASSERT_X(session.get() != nullptr, "launchInstance", "session is NULL"); @@ -1237,6 +1241,33 @@ void MainWindow::launchInstance(BaseInstance *instance, AuthSessionPtr session) proc->setLogin(session); proc->launch(); + + if (profile && qobject_cast(instance)) + { + BaseProfiler *profiler = MMC->currentProfiler()->createProfiler( + qobject_cast(instance), this); + QProgressDialog dialog; + dialog.setMinimum(0); + dialog.setMaximum(0); + dialog.setValue(0); + dialog.setLabelText(tr("Waiting for profiler...")); + dialog.show(); + connect(profiler, &BaseProfiler::readyToLaunch, [&dialog, this](const QString &message) + { + dialog.accept(); + QMessageBox msg; + msg.setText(tr("The launch of Minecraft itself is delayed until you press the " + "button. This is the right time to setup the profiler, as the " + "profiler server is running now.\n\n%1").arg(message)); + msg.setWindowTitle(tr("Waiting")); + msg.setIcon(QMessageBox::Information); + msg.addButton(tr("Launch"), QMessageBox::AcceptRole); + msg.exec(); + proc->write("launch onesix\n"); + }); + profiler->beginProfiling(proc); + dialog.exec(); + } } void MainWindow::onGameUpdateError(QString error) @@ -1416,6 +1447,15 @@ void MainWindow::on_actionEditInstNotes_triggered() } } +void MainWindow::on_actionProfileInstance_triggered() +{ + if (m_selectedInstance) + { + NagUtils::checkJVMArgs(m_selectedInstance->settings().get("JvmArgs").toString(), this); + doLaunch(true, true); + } +} + void MainWindow::instanceEnded() { this->show(); diff --git a/gui/MainWindow.h b/gui/MainWindow.h index 4d9e165d..66d98bc5 100644 --- a/gui/MainWindow.h +++ b/gui/MainWindow.h @@ -107,22 +107,24 @@ slots: void on_actionEditInstNotes_triggered(); + void on_actionProfileInstance_triggered(); + /*! * Launches the currently selected instance with the default account. * If no default account is selected, prompts the user to pick an account. */ - void doLaunch(bool online = true); + void doLaunch(bool online = true, bool profile = false); /*! * Launches the given instance with the given account. * This function assumes that the given account has a valid, usable access token. */ - void launchInstance(BaseInstance *instance, AuthSessionPtr session); + void launchInstance(BaseInstance *instance, AuthSessionPtr session, bool profile = false); /*! * Prepares the given instance for launch with the given account. */ - void updateInstance(BaseInstance *instance, AuthSessionPtr account); + void updateInstance(BaseInstance *instance, AuthSessionPtr account, bool profile = false); void onGameUpdateError(QString error); diff --git a/gui/MainWindow.ui b/gui/MainWindow.ui index 8cf26d18..81f66136 100644 --- a/gui/MainWindow.ui +++ b/gui/MainWindow.ui @@ -108,6 +108,7 @@ + @@ -528,12 +529,19 @@ Launch the selected instance. + + + Profile + + + Starts a profiling session with the current instance + + - - + diff --git a/gui/dialogs/SettingsDialog.cpp b/gui/dialogs/SettingsDialog.cpp index ef363f02..3039acc1 100644 --- a/gui/dialogs/SettingsDialog.cpp +++ b/gui/dialogs/SettingsDialog.cpp @@ -29,6 +29,8 @@ #include "logic/updater/UpdateChecker.h" +#include "logic/profiler/BaseProfiler.h" + #include #include #include @@ -368,6 +370,22 @@ void SettingsDialog::applySettings(SettingsObject *s) } s->set("PostExitCommand", ui->postExitCmdTextBox->text()); + + // Profilers + s->set("JProfilerPath", ui->jprofilerPathEdit->text()); + s->set("JVisualVMPath", ui->jvisualvmPathEdit->text()); + if (ui->profilerNoneBtn->isChecked()) + { + s->set("CurrentProfiler", QString()); + } + else if (ui->jprofilerBtn->isChecked()) + { + s->set("CurrentProfiler", "jprofiler"); + } + else if (ui->jvisualvmBtn->isChecked()) + { + s->set("CurrentProfiler", "jvisualvm"); + } } void SettingsDialog::loadSettings(SettingsObject *s) @@ -447,6 +465,23 @@ void SettingsDialog::loadSettings(SettingsObject *s) // Custom Commands ui->preLaunchCmdTextBox->setText(s->get("PreLaunchCommand").toString()); ui->postExitCmdTextBox->setText(s->get("PostExitCommand").toString()); + + // Profilers + ui->jprofilerPathEdit->setText(s->get("JProfilerPath").toString()); + ui->jvisualvmPathEdit->setText(s->get("JVisualVMPath").toString()); + const QString currentProfiler = s->get("CurrentProfiler").toString(); + if (currentProfiler.isEmpty()) + { + ui->profilerNoneBtn->setChecked(true); + } + else if (currentProfiler == "jprofiler") + { + ui->jprofilerBtn->setChecked(true); + } + else if (currentProfiler == "jvisualvm") + { + ui->jvisualvmBtn->setChecked(true); + } } void SettingsDialog::on_javaDetectBtn_clicked() @@ -503,3 +538,53 @@ void SettingsDialog::checkFinished(JavaCheckResult result) "or set the path to the java executable.")); } } + +void SettingsDialog::on_jprofilerPathBtn_clicked() +{ + QString raw_dir = QFileDialog::getExistingDirectory(this, tr("JProfiler Directory"), + ui->jprofilerPathEdit->text()); + QString cooked_dir = NormalizePath(raw_dir); + + // do not allow current dir - it's dirty. Do not allow dirs that don't exist + if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists()) + { + ui->jprofilerPathEdit->setText(cooked_dir); + } +} +void SettingsDialog::on_jprofilerCheckBtn_clicked() +{ + if (!ui->jprofilerPathEdit->text().isEmpty()) + { + QString error; + if (!MMC->profilers()["jprofiler"]->check(ui->jprofilerPathEdit->text(), &error)) + { + QMessageBox::critical(this, tr("Error"), + tr("Error while checking JProfiler install:\n%1").arg(error)); + } + } +} + +void SettingsDialog::on_jvisualvmPathBtn_clicked() +{ + QString raw_dir = QFileDialog::getOpenFileName(this, tr("JVisualVM Executable"), + ui->jvisualvmPathEdit->text()); + QString cooked_dir = NormalizePath(raw_dir); + + // do not allow current dir - it's dirty. Do not allow dirs that don't exist + if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists()) + { + ui->jvisualvmPathEdit->setText(cooked_dir); + } +} +void SettingsDialog::on_jvisualvmCheckBtn_clicked() +{ + if (!ui->jvisualvmPathEdit->text().isEmpty()) + { + QString error; + if (!MMC->profilers()["jvisualvm"]->check(ui->jvisualvmPathEdit->text(), &error)) + { + QMessageBox::critical(this, tr("Error"), + tr("Error while checking JVisualVM install:\n%1").arg(error)); + } + } +} diff --git a/gui/dialogs/SettingsDialog.h b/gui/dialogs/SettingsDialog.h index d7bbbeb3..60d569f9 100644 --- a/gui/dialogs/SettingsDialog.h +++ b/gui/dialogs/SettingsDialog.h @@ -75,6 +75,11 @@ slots: void checkFinished(JavaCheckResult result); + void on_jprofilerPathBtn_clicked(); + void on_jprofilerCheckBtn_clicked(); + void on_jvisualvmPathBtn_clicked(); + void on_jvisualvmCheckBtn_clicked(); + /*! * Updates the list of update channels in the combo box. */ diff --git a/gui/dialogs/SettingsDialog.ui b/gui/dialogs/SettingsDialog.ui index 54e7db7a..29cbbcba 100644 --- a/gui/dialogs/SettingsDialog.ui +++ b/gui/dialogs/SettingsDialog.ui @@ -863,6 +863,116 @@ + + + Profiling + + + + + + Active profiler + + + + + + None + + + + + + + JProfiler + + + + + + + JVisualVM + + + + + + + + + + JProfiler + + + + + + + + + + + ... + + + + + + + + + Check + + + + + + + + + + JVisualVM + + + + + + + + + + + ... + + + + + + + + + Check + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + @@ -938,7 +1048,7 @@ - + -- cgit