mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-16 09:50:40 +08:00
perf: 修改异步加载资源的方式
This commit is contained in:
@@ -437,10 +437,7 @@ void Assistant::msg_proc()
|
||||
continue;
|
||||
}
|
||||
|
||||
// 结构化绑定只能是引用,后续的pop会使引用失效,所以需要重新构造一份,这里采用了move的方式
|
||||
auto&& [temp_msg, temp_detail] = m_msg_queue.front();
|
||||
AsstMsg msg = temp_msg;
|
||||
json::value detail = std::move(temp_detail);
|
||||
auto [msg, detail] = std::move(m_msg_queue.front());
|
||||
m_msg_queue.pop();
|
||||
lock.unlock();
|
||||
|
||||
|
||||
@@ -7,27 +7,15 @@
|
||||
|
||||
bool asst::AbstractConfig::load(const std::filesystem::path& path)
|
||||
{
|
||||
return _load(path);
|
||||
}
|
||||
std::string class_name = utils::demangle(typeid(*this).name());
|
||||
|
||||
void asst::AbstractConfig::async_load(const std::filesystem::path& path)
|
||||
{
|
||||
m_load_future = std::async(std::launch::async, &AbstractConfig::_load, this, path);
|
||||
}
|
||||
|
||||
bool asst::AbstractConfig::_load(std::filesystem::path path)
|
||||
{
|
||||
if (!std::filesystem::exists(path) || !std::filesystem::is_regular_file(path)) {
|
||||
std::string class_name = utils::demangle(typeid(*this).name());
|
||||
Log.error(class_name, "file does not exist", path);
|
||||
Log.error(class_name, __FUNCTION__, "file does not exist", path);
|
||||
return false;
|
||||
}
|
||||
m_path = path;
|
||||
|
||||
std::unique_lock lock(m_load_mutex);
|
||||
|
||||
std::string class_name = utils::demangle(typeid(*this).name());
|
||||
LogTraceScope(class_name);
|
||||
LogTraceScope(class_name + " :: " + __FUNCTION__);
|
||||
Log.info(path);
|
||||
|
||||
auto ret = json::open(path, true);
|
||||
|
||||
@@ -17,15 +17,10 @@ namespace asst
|
||||
public:
|
||||
virtual ~AbstractConfig() override = default;
|
||||
virtual bool load(const std::filesystem::path& path) override;
|
||||
virtual void async_load(const std::filesystem::path& path);
|
||||
|
||||
protected:
|
||||
virtual bool parse(const json::value& json) = 0;
|
||||
|
||||
bool _load(std::filesystem::path path);
|
||||
|
||||
std::filesystem::path m_path;
|
||||
std::future<bool> m_load_future;
|
||||
std::mutex m_load_mutex;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -23,6 +23,54 @@
|
||||
#include "TemplResource.h"
|
||||
#include "Utils/Logger.hpp"
|
||||
|
||||
asst::ResourceLoader::ResourceLoader()
|
||||
{
|
||||
m_load_thread = std::thread(&ResourceLoader::load_thread_func, this);
|
||||
}
|
||||
|
||||
void asst::ResourceLoader::load_thread_func()
|
||||
{
|
||||
while (!m_load_thread_exit) {
|
||||
std::unique_lock<std::mutex> lock(m_load_mutex);
|
||||
|
||||
if (m_load_queue.empty()) {
|
||||
m_load_cv.wait(lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto [res_ptr, path] = std::move(m_load_queue.front());
|
||||
m_load_queue.pop_front();
|
||||
lock.unlock();
|
||||
|
||||
res_ptr->load(path);
|
||||
}
|
||||
}
|
||||
|
||||
void asst::ResourceLoader::add_load_queue(std::shared_ptr<AbstractResource> res_ptr, const std::filesystem::path& path)
|
||||
{
|
||||
if (!res_ptr || !std::filesystem::exists(path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_load_mutex);
|
||||
m_load_queue.emplace_back(std::move(res_ptr), path);
|
||||
m_load_cv.notify_all();
|
||||
}
|
||||
|
||||
asst::ResourceLoader::~ResourceLoader()
|
||||
{
|
||||
m_load_thread_exit = true;
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_load_mutex);
|
||||
m_load_cv.notify_all();
|
||||
}
|
||||
|
||||
if (m_load_thread.joinable()) {
|
||||
m_load_thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
bool asst::ResourceLoader::load(const std::filesystem::path& path)
|
||||
{
|
||||
if (!std::filesystem::exists(path)) {
|
||||
@@ -44,14 +92,10 @@ bool asst::ResourceLoader::load(const std::filesystem::path& path)
|
||||
// DEBUG 模式下这里同步加载,并检查返回值的,方便排查问题
|
||||
#define AsyncLoadConfig(Config, Filename) LoadResourceAndCheckRet(Config, Filename)
|
||||
#else
|
||||
#define AsyncLoadConfig(Config, Filename) \
|
||||
{ \
|
||||
auto full_path = path / Filename; \
|
||||
bool ret = async_load_config<Config>(full_path); \
|
||||
if (!ret) { \
|
||||
Log.error(#Config, " load failed, path:", full_path); \
|
||||
return false; \
|
||||
} \
|
||||
#define AsyncLoadConfig(Config, Filename) \
|
||||
{ \
|
||||
auto res_ptr = std::make_shared<Config>(); \
|
||||
add_load_queue(res_ptr, path / Filename); \
|
||||
}
|
||||
#endif // ASST_DEBUG
|
||||
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
#include "AbstractResource.h"
|
||||
|
||||
#include <deque>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
|
||||
#include "AbstractConfigWithTempl.h"
|
||||
#include "TemplResource.h"
|
||||
@@ -13,12 +15,17 @@ namespace asst
|
||||
class ResourceLoader final : public SingletonHolder<ResourceLoader>, public AbstractResource
|
||||
{
|
||||
public:
|
||||
virtual ~ResourceLoader() override = default;
|
||||
virtual ~ResourceLoader() override;
|
||||
|
||||
virtual bool load(const std::filesystem::path& path) override;
|
||||
bool loaded() const noexcept;
|
||||
|
||||
public:
|
||||
ResourceLoader();
|
||||
|
||||
private:
|
||||
void load_thread_func();
|
||||
|
||||
template <Singleton T>
|
||||
requires std::is_base_of_v<AbstractResource, T>
|
||||
bool load_resource(const std::filesystem::path& path)
|
||||
@@ -29,17 +36,6 @@ namespace asst
|
||||
return SingletonHolder<T>::get_instance().load(path);
|
||||
}
|
||||
|
||||
template <Singleton T>
|
||||
requires std::is_base_of_v<AbstractConfig, T>
|
||||
bool async_load_config(const std::filesystem::path& path)
|
||||
{
|
||||
if (!std::filesystem::exists(path)) {
|
||||
return m_loaded;
|
||||
}
|
||||
SingletonHolder<T>::get_instance().async_load(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <Singleton T>
|
||||
requires std::is_base_of_v<AbstractConfigWithTempl, T>
|
||||
bool load_resource_with_templ(const std::filesystem::path& path, const std::filesystem::path& templ_dir)
|
||||
@@ -54,7 +50,16 @@ namespace asst
|
||||
return load_resource<TemplResource>(templ_dir);
|
||||
}
|
||||
|
||||
void add_load_queue(std::shared_ptr<AbstractResource> res_ptr, const std::filesystem::path& path);
|
||||
|
||||
private:
|
||||
bool m_loaded = false;
|
||||
|
||||
// only for async load
|
||||
bool m_load_thread_exit = false;
|
||||
std::deque<std::pair<std::shared_ptr<AbstractResource>, std::filesystem::path>> m_load_queue;
|
||||
std::mutex m_load_mutex;
|
||||
std::condition_variable m_load_cv;
|
||||
std::thread m_load_thread;
|
||||
};
|
||||
} // namespace asst
|
||||
|
||||
Reference in New Issue
Block a user