[Input] Cache parsed YAML files to speed up repeated reads
This commit is contained in:
parent
40c403c07d
commit
a5bf674419
4 changed files with 37 additions and 5 deletions
|
|
@ -340,6 +340,12 @@ private:
|
|||
|
||||
std::unordered_map<std::string, AnyValue> m_data;
|
||||
UnitSystem m_units;
|
||||
|
||||
//! Cache for previously-parsed input (YAML) files. The key is the full path
|
||||
//! to the file, and the second element of the value is the last-modified
|
||||
//! time for the file, which is used to enable change detection.
|
||||
static std::unordered_map<std::string, std::pair<AnyMap, int>> s_cache;
|
||||
|
||||
friend class AnyValue;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
// at http://www.cantera.org/license.txt for license and copyright information.
|
||||
|
||||
#include "cantera/base/AnyMap.h"
|
||||
#include "application.h"
|
||||
#include "cantera/base/yaml.h"
|
||||
#include "cantera/base/stringUtils.h"
|
||||
#ifdef CT_USE_DEMANGLE
|
||||
|
|
@ -12,11 +13,14 @@
|
|||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <fstream>
|
||||
#include <mutex>
|
||||
|
||||
namespace ba = boost::algorithm;
|
||||
|
||||
namespace { // helper functions
|
||||
|
||||
std::mutex yaml_cache_mutex;
|
||||
|
||||
bool isFloat(const std::string& val)
|
||||
{
|
||||
// This function duplicates the logic of fpValueCheck, but doesn't throw
|
||||
|
|
@ -238,6 +242,8 @@ std::map<std::string, std::string> AnyValue::s_typenames = {
|
|||
{typeid(AnyMap).name(), "AnyMap"},
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, std::pair<AnyMap, int>> AnyMap::s_cache;
|
||||
|
||||
// Methods of class AnyValue
|
||||
|
||||
AnyValue::AnyValue()
|
||||
|
|
@ -745,17 +751,35 @@ AnyMap AnyMap::fromYamlString(const std::string& yaml) {
|
|||
|
||||
AnyMap AnyMap::fromYamlFile(const std::string& name) {
|
||||
std::string fullName = findInputFile(name);
|
||||
AnyMap amap;
|
||||
int mtime = get_modified_time(fullName);
|
||||
|
||||
// Check for an already-parsed YAML file with the same last-modified time,
|
||||
// and return that if possible
|
||||
std::unique_lock<std::mutex> lock(yaml_cache_mutex);
|
||||
auto iter = s_cache.find(fullName);
|
||||
if (iter != s_cache.end() && iter->second.second == mtime) {
|
||||
return iter->second.first;
|
||||
}
|
||||
|
||||
// Generate an AnyMap from the YAML file and store it in the cache
|
||||
auto& cache_item = s_cache[fullName];
|
||||
cache_item.second = mtime;
|
||||
try {
|
||||
YAML::Node node = YAML::LoadFile(fullName);
|
||||
amap = node.as<AnyMap>();
|
||||
cache_item.first = node.as<AnyMap>();
|
||||
cache_item.first.applyUnits(UnitSystem());
|
||||
} catch (YAML::Exception& err) {
|
||||
std::ifstream infile(fullName);
|
||||
s_cache.erase(fullName);
|
||||
throw CanteraError("AnyMap::fromYamlFile",
|
||||
formatYamlError(err, infile, name));
|
||||
} catch (CanteraError& err) {
|
||||
s_cache.erase(fullName);
|
||||
throw;
|
||||
}
|
||||
amap.applyUnits(UnitSystem());
|
||||
return amap;
|
||||
|
||||
// Return a copy of the AnyMap
|
||||
return cache_item.first;
|
||||
}
|
||||
|
||||
AnyMap::const_iterator begin(const AnyValue& v) {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ static std::mutex app_mutex;
|
|||
//! Mutex for controlling access to XML file storage
|
||||
static std::mutex xml_mutex;
|
||||
|
||||
static int get_modified_time(const std::string& path) {
|
||||
int get_modified_time(const std::string& path) {
|
||||
#ifdef _WIN32
|
||||
HANDLE hFile = CreateFile(path.c_str(), NULL, NULL,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ namespace Cantera
|
|||
|
||||
class XML_Node;
|
||||
|
||||
int get_modified_time(const std::string& path);
|
||||
|
||||
/*!
|
||||
* @defgroup globalData Global Data
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue