Use Nanotrace to generate startup performance report

Add various trace points to the code, including the plugin
initialization methods (centrally in plugin manager), code that is
scheduled on the event loop with QTimer::singleShot or
QMetaObject::invokeMethod during initialization, and code that is
triggered from ICore::coreOpened

Can be turned on by configuring with `BUILD_LIBRARY_NANOTRACE=ON`
Run with `-trace <file>` to write trace file. If Nanotrace is not built,
the added code expands to nothing.

Changes in Nanotrace:
- turned generated data to microseconds instead of nanoseconds, because
  that is what Chrome tracing expects
- fixed serialization of duration (needs to be an item of the event, not
  in a "arg" subitem)
- fixed shutdown() to reset the initEvent

Change-Id: I994de82023b820d771e1be0a859ebd8da0b73d4d
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
Eike Ziller
2023-08-30 15:04:29 +02:00
parent 66c8eda943
commit dab19c4a8c
24 changed files with 198 additions and 77 deletions

View File

@@ -1,5 +1,6 @@
add_subdirectory(3rdparty)
add_subdirectory(nanotrace)
add_subdirectory(advanceddockingsystem)
add_subdirectory(aggregation)
add_subdirectory(cplusplus)
@@ -8,7 +9,6 @@ add_subdirectory(glsl)
add_subdirectory(languageserverprotocol)
add_subdirectory(languageutils)
add_subdirectory(modelinglib)
add_subdirectory(nanotrace)
add_subdirectory(qmldebug)
add_subdirectory(qmleditorwidgets)
add_subdirectory(qmljs)

View File

@@ -26,3 +26,8 @@ extend_qtc_library(ExtensionSystem
DEPENDS Qt::Test
DEFINES WITH_TESTS
)
extend_qtc_library(ExtensionSystem
CONDITION TARGET Nanotrace
PUBLIC_DEPENDS Nanotrace
)

View File

@@ -22,6 +22,7 @@ const char *OptionsParser::TEST_OPTION = "-test";
const char *OptionsParser::NOTEST_OPTION = "-notest";
const char *OptionsParser::SCENARIO_OPTION = "-scenario";
const char *OptionsParser::PROFILE_OPTION = "-profile";
const char *OptionsParser::TRACE_OPTION = "-trace";
const char *OptionsParser::NO_CRASHCHECK_OPTION = "-no-crashcheck";
OptionsParser::OptionsParser(const QStringList &args,
@@ -60,6 +61,8 @@ bool OptionsParser::parse()
continue;
if (checkForProfilingOption())
continue;
if (checkForTraceOption())
continue;
if (checkForNoCrashcheckOption())
continue;
#ifdef WITH_TESTS
@@ -243,6 +246,16 @@ bool OptionsParser::checkForProfilingOption()
return true;
}
bool OptionsParser::checkForTraceOption()
{
if (m_currentArg != QLatin1String(TRACE_OPTION))
return false;
if (nextToken(RequiredToken)) {
m_pmPrivate->enableTracing(m_currentArg);
}
return true;
}
bool OptionsParser::checkForNoCrashcheckOption()
{
if (m_currentArg != QLatin1String(NO_CRASHCHECK_OPTION))

View File

@@ -28,6 +28,7 @@ public:
static const char *NOTEST_OPTION;
static const char *SCENARIO_OPTION;
static const char *PROFILE_OPTION;
static const char *TRACE_OPTION;
static const char *NO_CRASHCHECK_OPTION;
private:
@@ -41,6 +42,7 @@ private:
bool checkForAppOption();
bool checkForPluginOption();
bool checkForProfilingOption();
bool checkForTraceOption();
bool checkForNoCrashcheckOption();
bool checkForUnknownOption();
void forceDisableAllPluginsExceptTestedAndForceEnabled();

View File

@@ -10,6 +10,8 @@
#include "pluginspec.h"
#include "pluginspec_p.h"
#include <nanotrace/nanotrace.h>
#include <utils/algorithm.h>
#include <utils/benchmarker.h>
#include <utils/fileutils.h>
@@ -721,6 +723,12 @@ void PluginManager::formatOptions(QTextStream &str, int optionIndentation, int d
formatOption(str, QLatin1String(OptionsParser::PROFILE_OPTION),
QString(), QLatin1String("Profile plugin loading"),
optionIndentation, descriptionIndentation);
formatOption(str,
QLatin1String(OptionsParser::TRACE_OPTION),
QLatin1String("file"),
QLatin1String("Write trace file (CTF) for plugin loading"),
optionIndentation,
descriptionIndentation);
formatOption(str,
QLatin1String(OptionsParser::NO_CRASHCHECK_OPTION),
QString(),
@@ -932,9 +940,16 @@ PluginSpecPrivate *PluginManagerPrivate::privateSpec(PluginSpec *spec)
void PluginManagerPrivate::nextDelayedInitialize()
{
static bool first = true;
if (first) {
first = false;
NANOTRACE_BEGIN("ExtensionSystem", "DelayedInitialize");
}
while (!delayedInitializeQueue.empty()) {
PluginSpec *spec = delayedInitializeQueue.front();
const std::string specName = spec->name().toStdString();
delayedInitializeQueue.pop();
NANOTRACE_SCOPE(specName, specName + "::delayedInitialized");
profilingReport(">delayedInitialize", spec);
bool delay = spec->d->delayedInitialize();
profilingReport("<delayedInitialize", spec, &spec->d->performanceData.delayedInitialize);
@@ -948,6 +963,8 @@ void PluginManagerPrivate::nextDelayedInitialize()
if (m_profileTimer)
m_totalStartupMS = m_profileTimer->elapsed();
printProfilingSummary();
NANOTRACE_END("ExtensionSystem", "DelayedInitialize");
NANOTRACE_SHUTDOWN();
emit q->initializationDone();
#ifdef WITH_TESTS
if (PluginManager::testRunRequested())
@@ -1340,23 +1357,32 @@ void PluginManagerPrivate::loadPlugins()
const QVector<PluginSpec *> queue = loadQueue();
Utils::setMimeStartupPhase(MimeStartupPhase::PluginsLoading);
for (PluginSpec *spec : queue)
loadPlugin(spec, PluginSpec::Loaded);
{
NANOTRACE_SCOPE("ExtensionSystem", "Load");
for (PluginSpec *spec : queue)
loadPlugin(spec, PluginSpec::Loaded);
}
Utils::setMimeStartupPhase(MimeStartupPhase::PluginsInitializing);
for (PluginSpec *spec : queue)
loadPlugin(spec, PluginSpec::Initialized);
{
NANOTRACE_SCOPE("ExtensionSystem", "Initialize");
for (PluginSpec *spec : queue)
loadPlugin(spec, PluginSpec::Initialized);
}
Utils::setMimeStartupPhase(MimeStartupPhase::PluginsDelayedInitializing);
Utils::reverseForeach(queue, [this](PluginSpec *spec) {
loadPlugin(spec, PluginSpec::Running);
if (spec->state() == PluginSpec::Running) {
delayedInitializeQueue.push(spec);
} else {
// Plugin initialization failed, so cleanup after it
spec->d->kill();
}
});
{
NANOTRACE_SCOPE("ExtensionSystem", "ExtensionsInitialized");
Utils::reverseForeach(queue, [this](PluginSpec *spec) {
loadPlugin(spec, PluginSpec::Running);
if (spec->state() == PluginSpec::Running) {
delayedInitializeQueue.push(spec);
} else {
// Plugin initialization failed, so cleanup after it
spec->d->kill();
}
});
}
emit q->pluginsChanged();
Utils::setMimeStartupPhase(MimeStartupPhase::UpAndRunning);
@@ -1582,14 +1608,18 @@ void PluginManagerPrivate::loadPlugin(PluginSpec *spec, PluginSpec::State destSt
if (enableCrashCheck && destState < PluginSpec::Stopped)
lockFile.reset(new LockFile(this, spec));
const std::string specName = spec->name().toStdString();
switch (destState) {
case PluginSpec::Running:
case PluginSpec::Running: {
NANOTRACE_SCOPE(specName, specName + "::extensionsInitialized");
profilingReport(">initializeExtensions", spec);
spec->d->initializeExtensions();
profilingReport("<initializeExtensions",
spec,
&spec->d->performanceData.extensionsInitialized);
return;
}
case PluginSpec::Deleted:
profilingReport(">delete", spec);
spec->d->kill();
@@ -1613,16 +1643,20 @@ void PluginManagerPrivate::loadPlugin(PluginSpec *spec, PluginSpec::State destSt
}
}
switch (destState) {
case PluginSpec::Loaded:
case PluginSpec::Loaded: {
NANOTRACE_SCOPE(specName, specName + "::load");
profilingReport(">loadLibrary", spec);
spec->d->loadLibrary();
profilingReport("<loadLibrary", spec, &spec->d->performanceData.load);
break;
case PluginSpec::Initialized:
}
case PluginSpec::Initialized: {
NANOTRACE_SCOPE(specName, specName + "::initialize");
profilingReport(">initializePlugin", spec);
spec->d->initializePlugin();
profilingReport("<initializePlugin", spec, &spec->d->performanceData.initialize);
break;
}
case PluginSpec::Stopped:
profilingReport(">stop", spec);
if (spec->d->stop() == IPlugin::AsynchronousShutdown) {
@@ -1764,6 +1798,17 @@ void PluginManagerPrivate::increaseProfilingVerbosity()
PluginManager::startProfiling();
}
void PluginManagerPrivate::enableTracing(const QString &filePath)
{
const QString jsonFilePath = filePath.endsWith(".json") ? filePath : filePath + ".json";
#ifdef NANOTRACE_ENABLED
qDebug() << "Trace event file (CTF) will be saved at" << qPrintable(jsonFilePath);
#endif
NANOTRACE_INIT(QCoreApplication::applicationName().toStdString(),
"Main",
jsonFilePath.toStdString());
}
void PluginManagerPrivate::profilingReport(const char *what, const PluginSpec *spec, qint64 *target)
{
if (m_profileTimer) {

View File

@@ -59,6 +59,7 @@ public:
void resolveDependencies();
void enableDependenciesIndirectly();
void increaseProfilingVerbosity();
void enableTracing(const QString &filePath);
QString profilingSummary(qint64 *totalOut = nullptr) const;
void printProfilingSummary() const;
void profilingReport(const char *what, const PluginSpec *spec, qint64 *target = nullptr);

View File

@@ -73,6 +73,7 @@ struct TraceEvent
int64_t oh;
int64_t ts;
int64_t dur = 0;
std::vector< Nanotrace::Arg > args;
@@ -100,7 +101,10 @@ std::ostream& operator<<(std::ostream &stream, const TraceEvent &event)
<< "{ \"cat\":\"" << event.cat
<< "\", \"pid\":" << event.pid
<< ", \"tid\":\"" << event.tid << "\""
<< ", \"ts\":" << event.ts
<< ", \"ts\":" << event.ts;
if (event.dur > -1)
stream << ", \"dur\":" << event.dur;
stream
<< ", \"ph\":\"" << event.ph
<< "\", \"name\":\"" << event.name
<< "\", \"args\": { \"overhead\": " << event.oh;
@@ -112,7 +116,6 @@ std::ostream& operator<<(std::ostream &stream, const TraceEvent &event)
return stream;
}
void init(const std::string &process, const std::string &thread, const std::string &path)
{
auto now = Clock::now();
@@ -125,43 +128,40 @@ void init(const std::string &process, const std::string &thread, const std::stri
initEvent.ts = now;
events.reserve(eventCount);
events.push_back(TraceEvent {
getProcessId(),
std::this_thread::get_id(),
"process_name",
"",
'M',
0,
0,
{{"name", process}}
} );
events.push_back(TraceEvent{getProcessId(),
std::this_thread::get_id(),
"process_name",
"",
'M',
0,
0,
-1,
{{"name", process}}});
events.push_back(TraceEvent {
getProcessId(),
std::this_thread::get_id(),
"thread_name",
"",
'M',
0,
0,
{{"name", thread}}
} );
events.push_back(TraceEvent{getProcessId(),
std::this_thread::get_id(),
"thread_name",
"",
'M',
0,
0,
-1,
{{"name", thread}}});
if (std::ofstream stream(path, std::ios::trunc); stream.good())
stream << "{ \"traceEvents\": [\n";
else
std::cout << "Nanotrace::init: stream not good" << std::endl;
events.push_back(TraceEvent {
getProcessId(),
std::this_thread::get_id(),
"Initialize",
"Initialize",
'I',
0,
std::chrono::duration_cast< Units >(Clock::now() - now).count(),
{}
} );
events.push_back(TraceEvent{getProcessId(),
std::this_thread::get_id(),
"Initialize",
"Initialize",
'I',
0,
std::chrono::duration_cast<Units>(Clock::now() - now).count(),
-1,
{}});
initEvent.overhead = std::chrono::duration_cast< Units >(Clock::now() - now).count();
}
@@ -174,6 +174,7 @@ void shutdown()
stream << "\n] }";
else
std::cout << "Nanotrace::shutdown: stream not good" << std::endl;
initEvent = {};
}
void addTracePoint(
@@ -188,16 +189,15 @@ void addTracePoint(
auto now = Clock::now();
auto beg = std::chrono::duration_cast< Units >(now - initEvent.ts);
events.push_back( TraceEvent {
getProcessId(),
std::this_thread::get_id(),
name,
cat,
phase,
initEvent.overhead,
beg.count(),
{arguments}
} );
events.push_back(TraceEvent{getProcessId(),
std::this_thread::get_id(),
name,
cat,
phase,
initEvent.overhead,
beg.count(),
-1,
{arguments}});
if (events.size() >= eventCount - 1)
flush();
@@ -238,20 +238,19 @@ ScopeTracer::~ScopeTracer()
return;
auto now = Clock::now();
auto beg = std::chrono::duration_cast< Units >(m_start - initEvent.ts);
auto beg = std::chrono::duration_cast<Units>(m_start - initEvent.ts);
const int64_t dur = std::chrono::duration_cast<Units>(now - m_start).count();
m_args.push_back(Arg("dur", std::chrono::duration_cast< Units >(now - m_start).count()));
events.push_back(TraceEvent {
getProcessId(),
std::this_thread::get_id(),
m_name,
m_cat,
'X',
initEvent.overhead,
beg.count(),
{ m_args }
} );
m_args.push_back(Arg("dur", dur));
events.push_back(TraceEvent{getProcessId(),
std::this_thread::get_id(),
m_name,
m_cat,
'X',
initEvent.overhead,
beg.count(),
dur,
{m_args}});
if (events.size() >= eventCount - 1)
flush();

View File

@@ -50,7 +50,7 @@
namespace Nanotrace
{
using Units = std::chrono::nanoseconds;
using Units = std::chrono::microseconds;
using Clock = std::chrono::high_resolution_clock;
using TimePoint = std::chrono::time_point< Clock >;

View File

@@ -276,6 +276,11 @@ extend_qtc_library(Utils
fsengine/filepathinfocache.h
)
extend_qtc_library(Utils
CONDITION TARGET Nanotrace
DEPENDS Nanotrace
)
if (WIN32)
add_qtc_executable(qtcreator_ctrlc_stub
DEPENDS user32 shell32

View File

@@ -13,6 +13,8 @@
#include "algorithm.h"
#include <nanotrace/nanotrace.h>
#include <QFile>
#include <QFileInfo>
#include <QStandardPaths>
@@ -90,6 +92,7 @@ static void updateOverriddenMimeTypes(std::vector<std::unique_ptr<MimeProviderBa
void MimeDatabasePrivate::loadProviders()
{
NANOTRACE_SCOPE("Utils", "MimeDatabasePrivate::loadProviders");
#if 0
// We use QStandardPaths every time to check if new files appeared
const QStringList mimeDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime"), QStandardPaths::LocateDirectory);

View File

@@ -49,6 +49,8 @@
#include <qtsupport/qtversionmanager.h>
#include <nanotrace/nanotrace.h>
#include <QTimer>
using namespace ProjectExplorer;
@@ -141,6 +143,7 @@ void AndroidPlugin::kitsRestored()
void AndroidPlugin::askUserAboutAndroidSetup()
{
NANOTRACE_SCOPE("Android", "AndroidPlugin::askUserAboutAndroidSetup");
if (!Core::ICore::infoBar()->canInfoBeAdded(kSetupAndroidSetting))
return;

View File

@@ -17,6 +17,8 @@
#include <utils/pointeralgorithm.h>
#include <utils/qtcassert.h>
#include <nanotrace/nanotrace.h>
using namespace Core;
using namespace Utils;
@@ -134,6 +136,7 @@ CMakeTool *CMakeToolManager::findById(const Id &id)
void CMakeToolManager::restoreCMakeTools()
{
NANOTRACE_SCOPE("CMakeProjectManager", "CMakeToolManager::restoreCMakeTools");
Internal::CMakeToolSettingsAccessor::CMakeTools tools
= d->m_accessor.restoreCMakeTools(ICore::dialogParent());
d->m_cmakeTools = std::move(tools.cmakeTools);

View File

@@ -12,6 +12,8 @@
#include <utils/fadingindicator.h>
#include <utils/qtcassert.h>
#include <nanotrace/nanotrace.h>
#include <QAction>
#include <QApplication>
#include <QDebug>

View File

@@ -64,6 +64,8 @@
#include <utils/terminalcommand.h>
#include <utils/utilsicons.h>
#include <nanotrace/nanotrace.h>
#include <QAbstractProxyModel>
#include <QActionGroup>
#include <QApplication>
@@ -1549,6 +1551,7 @@ QPrinter *MainWindow::printer() const
void MainWindow::restoreWindowState()
{
NANOTRACE_SCOPE("Core", "MainWindow::restoreWindowState");
QSettings *settings = PluginManager::settings();
settings->beginGroup(QLatin1String(settingsGroup));
if (!restoreGeometry(settings->value(QLatin1String(windowGeometryKey)).toByteArray()))

View File

@@ -28,6 +28,8 @@
#include <utils/stringutils.h>
#include <utils/stylehelper.h>
#include <nanotrace/nanotrace.h>
#include <QAction>
#include <QActionGroup>
#include <QFutureInterface>
@@ -400,6 +402,7 @@ static QString determineSessionToRestoreAtStartup()
void SessionManagerPrivate::restoreStartupSession()
{
NANOTRACE_SCOPE("Core", "SessionManagerPrivate::restoreStartupSession");
m_isStartupSessionRestored = true;
QString sessionToRestoreAtStartup = determineSessionToRestoreAtStartup();
if (!sessionToRestoreAtStartup.isEmpty())

View File

@@ -27,6 +27,8 @@
#include <utils/treemodel.h>
#include <utils/winutils.h>
#include <nanotrace/nanotrace.h>
#include <QDebug>
#include <QDir>
#include <QFileInfo>
@@ -832,6 +834,7 @@ void DebuggerItemModel::saveDebuggers()
void DebuggerItemManager::restoreDebuggers()
{
NANOTRACE_SCOPE("Debugger", "DebuggerItemManager::restoreDebuggers");
itemModel().restoreDebuggers();
}

View File

@@ -61,6 +61,8 @@
#include <vcsbase/vcscommand.h>
#include <vcsbase/vcsoutputwindow.h>
#include <nanotrace/nanotrace.h>
#include <QAction>
#include <QApplication>
#include <QDebug>
@@ -680,6 +682,7 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage)
auto cmdContext = new QObject(this);
connect(ICore::instance(), &ICore::coreOpened, cmdContext, [this, cmdContext, arguments] {
NANOTRACE_SCOPE("Git", "GitPlugin::initialize::coreOpened");
remoteCommand(arguments, QDir::currentPath(), {});
cmdContext->deleteLater();
});

View File

@@ -26,6 +26,8 @@
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
#include <nanotrace/nanotrace.h>
#include <QAction>
#include <QHash>
#include <QLabel>
@@ -153,6 +155,7 @@ void KitManager::destroy()
void KitManager::restoreKits()
{
NANOTRACE_SCOPE("ProjectExplorer", "KitManager::restoreKits");
QTC_ASSERT(!d->m_initialized, return );
connect(ICore::instance(), &ICore::saveSettingsRequested, &KitManager::saveKits);

View File

@@ -134,6 +134,8 @@
#include <utils/tooltip/tooltip.h>
#include <utils/utilsicons.h>
#include <nanotrace/nanotrace.h>
#include <QAction>
#include <QActionGroup>
#include <QApplication>
@@ -2126,6 +2128,7 @@ void ProjectExplorerPlugin::extensionsInitialized()
void ProjectExplorerPlugin::restoreKits()
{
NANOTRACE_SCOPE("ProjectExplorer", "ProjectExplorerPlugin::restoreKits");
ExtraAbi::load(); // Load this before Toolchains!
ToolChainManager::restoreToolChains();
KitManager::restoreKits();

View File

@@ -16,6 +16,8 @@
#include <utils/qtcassert.h>
#include <utils/algorithm.h>
#include <nanotrace/nanotrace.h>
#include <QSettings>
using namespace Utils;
@@ -102,6 +104,7 @@ ToolChainManager *ToolChainManager::instance()
void ToolChainManager::restoreToolChains()
{
NANOTRACE_SCOPE("ProjectExplorer", "ToolChainManager::restoreToolChains");
QTC_ASSERT(!d->m_accessor, return);
d->m_accessor = std::make_unique<Internal::ToolChainSettingsAccessor>();

View File

@@ -12,6 +12,8 @@
#include <utils/algorithm.h>
#include <nanotrace/nanotrace.h>
#include <QElapsedTimer>
#include <QGuiApplication>
#include <QLoggingCategory>
@@ -56,6 +58,9 @@ static Toolchains autoDetectToolChains(const ToolchainDetector &detector)
{
Toolchains result;
for (ToolChainFactory *f : ToolChainFactory::allToolChainFactories()) {
NANOTRACE_SCOPE_ARGS("ProjectExplorer",
"ToolChainSettingsAccessor::autoDetectToolChains",
{"factory", f->displayName().toStdString()});
QElapsedTimer et;
et.start();
result.append(f->autoDetect(detector));
@@ -179,6 +184,7 @@ ToolChainSettingsAccessor::ToolChainSettingsAccessor()
Toolchains ToolChainSettingsAccessor::restoreToolChains(QWidget *parent) const
{
NANOTRACE_SCOPE("ProjectExplorer", "ToolChainSettingsAccessor::restoreToolChains");
// read all tool chains from SDK
const Toolchains systemFileTcs = toolChains(
restoreSettings(Core::ICore::installerResourcePath(TOOLCHAIN_FILENAME), parent));

View File

@@ -10,6 +10,8 @@
#include <QLoggingCategory>
#include <qtsupport/qtversionmanager.h>
#include <nanotrace/nanotrace.h>
#include <limits>
using namespace QtSupport;

View File

@@ -24,6 +24,8 @@
#include <utils/process.h>
#include <utils/qtcassert.h>
#include <nanotrace/nanotrace.h>
#include <QDir>
#include <QFile>
#include <QLoggingCategory>
@@ -141,8 +143,11 @@ QtVersionManagerImpl &qtVersionManagerImpl()
void QtVersionManagerImpl::triggerQtVersionRestore()
{
disconnect(ToolChainManager::instance(), &ToolChainManager::toolChainsLoaded,
this, &QtVersionManagerImpl::triggerQtVersionRestore);
NANOTRACE_SCOPE("QtSupport", "QtVersionManagerImpl::triggerQtVersionRestore");
disconnect(ToolChainManager::instance(),
&ToolChainManager::toolChainsLoaded,
this,
&QtVersionManagerImpl::triggerQtVersionRestore);
bool success = restoreQtVersions();
updateFromInstaller(false);
@@ -153,8 +158,10 @@ void QtVersionManagerImpl::triggerQtVersionRestore()
findSystemQt();
}
emit QtVersionManager::instance()->qtVersionsLoaded();
{
NANOTRACE_SCOPE("QtSupport", "QtVersionManagerImpl::qtVersionsLoaded");
emit QtVersionManager::instance()->qtVersionsLoaded();
}
emit QtVersionManager::instance()->qtVersionsChanged(
m_versions.keys(), QList<int>(), QList<int>());

View File

@@ -45,6 +45,8 @@
#include <utils/stringutils.h>
#include <utils/theme/theme.h>
#include <nanotrace/nanotrace.h>
#include <QAbstractListModel>
#include <QApplication>
#include <QDesktopServices>
@@ -559,6 +561,8 @@ void StudioWelcomePlugin::extensionsInitialized()
if (showSplashScreen()) {
connect(Core::ICore::instance(), &Core::ICore::coreOpened, this, [this] {
NANOTRACE_SCOPE("StudioWelcome",
"StudioWelcomePlugin::extensionsInitialized::coreOpened");
Core::ModeManager::setModeStyle(Core::ModeManager::Style::Hidden);
if (Utils::HostOsInfo::isMacHost()) {
s_viewWindow = new QQuickView(Core::ICore::mainWindow()->windowHandle());