From 7c45b9bc8dc71291dc3b6301c9c0818f7655e8ce Mon Sep 17 00:00:00 2001 From: Oliver Hamlet Date: Thu, 25 Jun 2015 15:06:01 +0100 Subject: [PATCH] Check plugin sizes when loading again. Plugin size checking was removed a couple of commits ago when hardware concurrency usage was implemented, but it makes sense to spread the data between the threads as evenly as possible, as randomly assigning plugins to threads could lead to all the big plugins being loaded in one thread, which is inefficient. --- src/backend/game/game.cpp | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/backend/game/game.cpp b/src/backend/game/game.cpp index 2ba29e01..9ef05447 100644 --- a/src/backend/game/game.cpp +++ b/src/backend/game/game.cpp @@ -123,17 +123,26 @@ namespace loot { } void Game::LoadPlugins(bool headersOnly) { - // First find out how many plugins there are. + uintmax_t meanFileSize = 0; + map sizeMap; + + // First find out how many plugins there are, and their sizes. BOOST_LOG_TRIVIAL(trace) << "Scanning for plugins in " << this->DataPath(); for (fs::directory_iterator it(this->DataPath()); it != fs::directory_iterator(); ++it) { if (fs::is_regular_file(it->status()) && Plugin(it->path().filename().string()).IsValid(*this)) { Plugin temp(it->path().filename().string()); BOOST_LOG_TRIVIAL(info) << "Found plugin: " << temp.Name(); + uintmax_t fileSize = fs::file_size(it->path()); + meanFileSize += fileSize; + //Insert the lowercased name as a key for case-insensitive matching. - plugins.insert(pair(boost::locale::to_lower(temp.Name()), temp)); + std::string name = boost::locale::to_lower(temp.Name()); + plugins.insert(pair(name, temp)); + sizeMap.insert(pair(fileSize, name)); } } + meanFileSize /= sizeMap.size(); //Rounding error, but not important. // Get the number of threads to use. // hardware_concurrency() may be zero, if so then use only one thread. @@ -142,16 +151,18 @@ namespace loot { // Divide the plugins up by thread. unsigned int pluginsPerThread = ceil((double)plugins.size() / threadsToUse); + std::vector::iterator>> pluginGroups(threadsToUse); BOOST_LOG_TRIVIAL(info) << "Loading " << plugins.size() << " plugins using " << threadsToUse << " threads, with up to " << pluginsPerThread << " plugins per thread."; - std::vector::iterator>> pluginGroups(threadsToUse); - size_t pluginGroup = 0; - for (auto it = plugins.begin(); it != plugins.end(); ++it) { - if (pluginGroups[pluginGroup].size() == pluginsPerThread) { - ++pluginGroup; - } - BOOST_LOG_TRIVIAL(trace) << "Adding plugin " << it->second.Name() << " to loading group " << pluginGroup; - pluginGroups[pluginGroup].push_back(it); + // The plugins should be split between the threads so that the data + // load is as evenly spread as possible. + size_t currentGroup = 0; + for (auto& plugin : sizeMap) { + if (currentGroup == threadsToUse) + currentGroup = 0; + BOOST_LOG_TRIVIAL(trace) << "Adding plugin " << plugin.second << " to loading group " << currentGroup; + pluginGroups[currentGroup].push_back(plugins.find(plugin.second)); + ++currentGroup; } // Load the plugins.