From a19773873a08de694411024a21871bdf02332bae Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Fri, 23 Apr 2021 22:35:04 -0400 Subject: [PATCH] performance: Cache CLI2::canonicalize lookups Canonicalization of attributes or attribute prefixes happens once per every single task considered in the filtering process. It maps short, prefixed names to their full-length versions, for example: "pro" -> "project" in the expression "project:Home" It follows that such process is not task-dependant and as such the lookups can be cached. --- src/CLI2.cpp | 15 ++++++++++++++- src/CLI2.h | 4 +++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/CLI2.cpp b/src/CLI2.cpp index 53d8366e2..cd57e4dbd 100644 --- a/src/CLI2.cpp +++ b/src/CLI2.cpp @@ -699,8 +699,19 @@ const std::vector CLI2::getWords () bool CLI2::canonicalize ( std::string& canonicalized, const std::string& category, - const std::string& value) const + const std::string& value) { + // Utilize a cache mapping of (category, value) -> canonicalized value. + // This cache does not need to be invalidated, because entities are defined + // only once per initialization of the Context object. + int cache_key = 31 * std::hash{} (category) + std::hash{} (value); + auto cache_result = _canonical_cache.find (cache_key); + if (cache_result != _canonical_cache.end()) + { + canonicalized = cache_result->second; + return true; + } + // Extract a list of entities for category. std::vector options; auto c = _entities.equal_range (category); @@ -710,6 +721,7 @@ bool CLI2::canonicalize ( if (value == e->second) { canonicalized = value; + _canonical_cache[cache_key] = value; return true; } @@ -721,6 +733,7 @@ bool CLI2::canonicalize ( if (autoComplete (value, options, matches, minimumMatchLength) == 1) { canonicalized = matches[0]; + _canonical_cache[cache_key] = matches[0]; return true; } diff --git a/src/CLI2.h b/src/CLI2.h index 6a276a758..b785c9f04 100644 --- a/src/CLI2.h +++ b/src/CLI2.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -77,7 +78,7 @@ public: void addContext (bool readable, bool writeable); void prepareFilter (); const std::vector getWords (); - bool canonicalize (std::string&, const std::string&, const std::string&) const; + bool canonicalize (std::string&, const std::string&, const std::string&); std::string getBinary () const; std::string getCommand (bool canonical = true) const; const std::string dump (const std::string& title = "CLI2 Parser") const; @@ -109,6 +110,7 @@ private: public: std::multimap _entities {}; std::map _aliases {}; + std::unordered_map _canonical_cache {}; std::vector _original_args {}; std::vector _args {};