From ab28eedc313d54a037b4d62bce0d3d243423dcf7 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 4 Dec 2015 13:11:50 +0200 Subject: [PATCH] Cache the total data size in ResourceManager Calculating it again every frame turned out to be a fairly large performance hit in applications with many different resources. --- source/resource.h | 4 ++++ source/resourcemanager.cpp | 43 ++++++++++++++++++++++++-------------- source/resourcemanager.h | 7 +++++-- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/source/resource.h b/source/resource.h index 01c604c3..571d1ea5 100644 --- a/source/resource.h +++ b/source/resource.h @@ -38,7 +38,11 @@ public: virtual int get_load_priority() const { return 0; } virtual AsyncLoader *load(IO::Seekable &, const Resources * = 0) = 0; virtual bool is_loaded() const; + + /** Returns the amount of graphics memory used by this resource. The + returned value must not change while the resource is loaded. */ virtual UInt64 get_data_size() const = 0; + virtual void unload() = 0; }; diff --git a/source/resourcemanager.cpp b/source/resourcemanager.cpp index 52e5866a..6d383de4 100644 --- a/source/resourcemanager.cpp +++ b/source/resourcemanager.cpp @@ -126,6 +126,7 @@ void ResourceManager::load_resource(Resource &r) managed.start_loading(); while(!managed.loader->process()) ; managed.finish_loading(true); + total_data_size += managed.data_size; } } @@ -181,7 +182,10 @@ void ResourceManager::tick() bool do_unload = (frame>=next_unload); if(thread.sync()) + { + total_data_size += thread.get_and_reset_loaded_data_size(); do_unload = true; + } if(thread.needs_work() && !queue.empty()) dispatch_work(); @@ -231,14 +235,17 @@ void ResourceManager::unload_by_age() for(ResourceMap::iterator i=resources.begin(); i!=resources.end(); ++i) if(i->second.state==ManagedResource::LOADED && i->second.last_usedsecond.unload(); + total_data_size -= i->second.data_size; + } } void ResourceManager::unload_by_size() { unsigned unload_limit = frame-min_retain_frames; - while(get_total_data_size_()>size_limit) + while(total_data_size>size_limit) { ManagedResource *best = 0; UInt64 best_impact = 0; @@ -257,24 +264,10 @@ void ResourceManager::unload_by_size() break; best->unload(); + total_data_size -= best->data_size; } } -UInt64 ResourceManager::get_total_data_size_() const -{ - UInt64 total = 0; - for(ResourceMap::const_iterator i=resources.begin(); i!=resources.end(); ++i) - if(i->second.state==ManagedResource::LOADED) - total += i->second.data_size; - return total; -} - -UInt64 ResourceManager::get_total_data_size() const -{ - MutexLock lock(map_mutex); - return get_total_data_size_(); -} - bool ResourceManager::age_order(ManagedResource *mr1, ManagedResource *mr2) { return mr1->last_used>mr2->last_used; @@ -449,6 +442,11 @@ void ResourceManager::LoadingThread::remove_resource(ManagedResource &r) Time::sleep(Time::msec); r.finish_loading(); + if(r.state==ManagedResource::LOADED) + { + MutexLock lock(data_size_mutex); + loaded_data_size += r.data_size; + } } bool ResourceManager::LoadingThread::try_remove_resource(ManagedResource &r) @@ -501,6 +499,11 @@ bool ResourceManager::LoadingThread::sync() if(managed->state==ManagedResource::LOAD_ERROR || managed->process(true)) { managed->finish_loading(); + if(managed->state==ManagedResource::LOADED) + { + MutexLock lock(data_size_mutex); + loaded_data_size += managed->data_size; + } any_finished = true; --size; @@ -520,6 +523,14 @@ bool ResourceManager::LoadingThread::sync() return any_finished; } +UInt64 ResourceManager::LoadingThread::get_and_reset_loaded_data_size() +{ + MutexLock lock(data_size_mutex); + UInt64 result = loaded_data_size; + loaded_data_size = 0; + return result; +} + void ResourceManager::LoadingThread::terminate() { done = true; diff --git a/source/resourcemanager.h b/source/resourcemanager.h index 9378d920..afa2c2d0 100644 --- a/source/resourcemanager.h +++ b/source/resourcemanager.h @@ -88,6 +88,8 @@ private: unsigned capacity; unsigned size; std::list error_queue; + Mutex data_size_mutex; + UInt64 loaded_data_size; volatile bool done; public: @@ -106,6 +108,7 @@ private: public: bool sync(); bool needs_work() const { return size