sys: Improved startup time by running startup tasks in parallel

This commit is contained in:
WerWolv 2022-09-19 16:54:19 +02:00
parent 7b61268f22
commit 4c01a749de
8 changed files with 54 additions and 25 deletions

View File

@ -171,6 +171,8 @@ namespace hex {
void setGPUVendor(const std::string &vendor);
void setPortableVersion(bool enabled);
void addInitArgument(const std::string &key, const std::string &value = { });
}
struct ProgramArguments {

View File

@ -3,6 +3,7 @@
#include <hex.hpp>
#include <chrono>
#include <mutex>
#include <fmt/core.h>
#include <fmt/color.h>
@ -30,6 +31,9 @@ namespace hex::log {
template<typename... T>
[[maybe_unused]] void print(const fmt::text_style &ts, const std::string &level, const std::string &fmt, auto... args) {
static std::mutex logMutex;
std::scoped_lock lock(logMutex);
auto dest = getDestination();
printPrefix(dest, ts, level);

View File

@ -385,6 +385,13 @@ namespace hex {
s_portableVersion = enabled;
}
void addInitArgument(const std::string &key, const std::string &value) {
static std::mutex initArgumentsMutex;
std::scoped_lock lock(initArgumentsMutex);
getInitArguments()[key] = value;
}
}

View File

@ -19,8 +19,8 @@ namespace hex::init {
bool loop();
void addStartupTask(const std::string &taskName, const TaskFunction &task) {
this->m_tasks.emplace_back(taskName, task);
void addStartupTask(const std::string &taskName, const TaskFunction &task, bool async) {
this->m_tasks.emplace_back(taskName, task, async);
}
private:
@ -37,7 +37,7 @@ namespace hex::init {
std::future<bool> processTasksAsync();
std::vector<std::pair<std::string, TaskFunction>> m_tasks;
std::vector<std::tuple<std::string, TaskFunction, bool>> m_tasks;
std::string m_gpuVendor;
};

View File

@ -9,6 +9,7 @@ namespace hex::init {
struct Task {
std::string name;
std::function<bool()> function;
bool async;
};
std::vector<Task> getInitTasks();

View File

@ -43,15 +43,27 @@ namespace hex::init {
return std::async(std::launch::async, [this] {
bool status = true;
for (const auto &[name, task] : this->m_tasks) {
{
u32 tasksCompleted = 0;
for (const auto &[name, task, async] : this->m_tasks) {
if (!async) {
std::lock_guard guard(this->m_progressMutex);
this->m_currTaskName = name;
}
try {
auto runTask = [&, task = task] {
if (!task())
status = false;
tasksCompleted++;
};
try {
if (async) {
std::thread(runTask).detach();
} else {
runTask();
}
} catch (std::exception &e) {
log::error("Init task '{}' threw an exception: {}", name, e.what());
status = false;
@ -63,6 +75,9 @@ namespace hex::init {
}
}
while (tasksCompleted < this->m_tasks.size())
std::this_thread::sleep_for(100ms);
// Small extra delay so the last progress step is visible
std::this_thread::sleep_for(200ms);

View File

@ -40,7 +40,7 @@ namespace hex::init {
auto latestVersion = releases.body["tag_name"].get<std::string_view>();
if (latestVersion != currVersion)
ImHexApi::System::getInitArguments().insert({ "update-available", latestVersion.data() });
ImHexApi::System::impl::addInitArgument("update-available", latestVersion.data());
return true;
}
@ -52,7 +52,7 @@ namespace hex::init {
if (tip.code != 200)
return false;
ImHexApi::System::getInitArguments().insert({ "tip-of-the-day", tip.body });
ImHexApi::System::impl::addInitArgument("tip-of-the-day", tip.body);
return true;
}
@ -99,7 +99,7 @@ namespace hex::init {
}
if (!result)
ImHexApi::System::getInitArguments().insert({ "folder-creation-error", {} });
ImHexApi::System::impl::addInitArgument("folder-creation-error");
return result;
}
@ -246,7 +246,7 @@ namespace hex::init {
if (plugins.empty()) {
log::error("No plugins found!");
ImHexApi::System::getInitArguments().insert({ "no-plugins", {} });
ImHexApi::System::impl::addInitArgument("no-plugins");
return false;
}
@ -274,17 +274,17 @@ namespace hex::init {
if (loadErrors == plugins.size()) {
log::error("No plugins loaded successfully!");
ImHexApi::System::getInitArguments().insert({ "no-plugins", {} });
ImHexApi::System::impl::addInitArgument("no-plugins");
return false;
}
if (builtinPlugins == 0) {
log::error("Built-in plugin not found!");
ImHexApi::System::getInitArguments().insert({ "no-builtin-plugin", {} });
ImHexApi::System::impl::addInitArgument("no-builtin-plugin");
return false;
} else if (builtinPlugins > 1) {
log::error("Found more than one built-in plugin!");
ImHexApi::System::getInitArguments().insert({ "multiple-builtin-plugins", {} });
ImHexApi::System::impl::addInitArgument("multiple-builtin-plugins");
return false;
}
@ -324,20 +324,20 @@ namespace hex::init {
std::vector<Task> getInitTasks() {
return {
{"Checking for updates...", checkForUpdates },
{ "Downloading information...", downloadInformation},
{ "Creating directories...", createDirectories },
{ "Loading settings...", loadSettings },
{ "Loading plugins...", loadPlugins },
{ "Loading fonts...", loadFonts },
{ "Checking for updates...", checkForUpdates, false },
{ "Downloading information...", downloadInformation, true },
{ "Loading fonts...", loadFonts, true },
{ "Creating directories...", createDirectories, false },
{ "Loading settings...", loadSettings, false },
{ "Loading plugins...", loadPlugins, false },
};
}
std::vector<Task> getExitTasks() {
return {
{"Saving settings...", storeSettings },
{ "Cleaning up shared data...", deleteSharedData},
{ "Unloading plugins...", unloadPlugins },
{ "Saving settings...", storeSettings, false },
{ "Cleaning up shared data...", deleteSharedData, false },
{ "Unloading plugins...", unloadPlugins, false },
};
}

View File

@ -33,8 +33,8 @@ int main(int argc, char **argv, char **envp) {
init::WindowSplash splashWindow;
for (const auto &[name, task] : init::getInitTasks())
splashWindow.addStartupTask(name, task);
for (const auto &[name, task, async] : init::getInitTasks())
splashWindow.addStartupTask(name, task, async);
if (!splashWindow.loop())
ImHexApi::System::getInitArguments().insert({ "tasks-failed", {} });
@ -42,7 +42,7 @@ int main(int argc, char **argv, char **envp) {
// Clean up
ON_SCOPE_EXIT {
for (const auto &[name, task] : init::getExitTasks())
for (const auto &[name, task, async] : init::getExitTasks())
task();
};