perf: 修改异步加载资源的方式

This commit is contained in:
MistEO
2023-05-02 15:16:07 +08:00
parent 85b964020b
commit 7dc0fd348d
5 changed files with 73 additions and 44 deletions

View File

@@ -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();

View File

@@ -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);

View File

@@ -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;
};
}

View File

@@ -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

View File

@@ -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