From 3fbb25b2cc66f236a39b728d20e5d44da23612ac Mon Sep 17 00:00:00 2001 From: Evan Martin Date: Mon, 12 Sep 2011 11:44:12 -0700 Subject: generalize the pattern of hash_map, use in BuildLog Refactor the code in StatCache for use in BuildLog. Now both use hash tables where the keys are const char*. Removes another 30ms from Chrome no-op builds. --- src/build_log.cc | 14 +++++++------- src/build_log.h | 4 +++- src/hash_map.h | 29 +++++++++++++++++++++++++++++ src/stat_cache.cc | 5 ++--- src/stat_cache.h | 22 +--------------------- 5 files changed, 42 insertions(+), 32 deletions(-) diff --git a/src/build_log.cc b/src/build_log.cc index b21a755..79143bf 100644 --- a/src/build_log.cc +++ b/src/build_log.cc @@ -91,15 +91,15 @@ void BuildLog::RecordCommand(Edge* edge, int start_time, int end_time) { for (vector::iterator out = edge->outputs_.begin(); out != edge->outputs_.end(); ++out) { const string& path = (*out)->file_->path_; - Log::iterator i = log_.find(path); + Log::iterator i = log_.find(path.c_str()); LogEntry* log_entry; if (i != log_.end()) { log_entry = i->second; } else { log_entry = new LogEntry; - log_.insert(make_pair(path, log_entry)); + log_entry->output = path; + log_.insert(make_pair(log_entry->output.c_str(), log_entry)); } - log_entry->output = path; log_entry->command = command; log_entry->start_time = start_time; log_entry->end_time = end_time; @@ -171,17 +171,17 @@ bool BuildLog::Load(const string& path, string* err) { continue; LogEntry* entry; - Log::iterator i = log_.find(output); + Log::iterator i = log_.find(output.c_str()); if (i != log_.end()) { entry = i->second; } else { entry = new LogEntry; - log_.insert(make_pair(output, entry)); + entry->output = output; + log_.insert(make_pair(entry->output.c_str(), entry)); ++unique_entry_count; } ++total_entry_count; - entry->output = output; entry->start_time = start_time; entry->end_time = end_time; entry->command = string(start, end - start); @@ -205,7 +205,7 @@ bool BuildLog::Load(const string& path, string* err) { } BuildLog::LogEntry* BuildLog::LookupByOutput(const string& path) { - Log::iterator i = log_.find(path); + Log::iterator i = log_.find(path.c_str()); if (i != log_.end()) return i->second; return NULL; diff --git a/src/build_log.h b/src/build_log.h index f45cbde..4a11c1a 100644 --- a/src/build_log.h +++ b/src/build_log.h @@ -19,6 +19,8 @@ #include using namespace std; +#include "hash_map.h" + struct BuildConfig; struct Edge; @@ -64,7 +66,7 @@ struct BuildLog { /// Rewrite the known log entries, throwing away old data. bool Recompact(const string& path, string* err); - typedef map Log; + typedef ExternalStringHashMap::Type Log; Log log_; FILE* log_file_; BuildConfig* config_; diff --git a/src/hash_map.h b/src/hash_map.h index 346a34e..1025f71 100644 --- a/src/hash_map.h +++ b/src/hash_map.h @@ -15,6 +15,8 @@ #ifndef NINJA_MAP_H_ #define NINJA_MAP_H_ +#include + #ifdef _MSC_VER #include @@ -37,4 +39,31 @@ struct hash { #endif +/// Equality binary predicate for const char*. +struct ExternalStringEq { + bool operator()(const char* a, const char* b) { + return strcmp(a, b) == 0; + } +}; + +/// Hash functor for const char*. +struct ExternalStringHash { + size_t operator()(const char* key) const { +#ifdef _MSC_VER + return stdext::hash()(key); +#else + return __gnu_cxx::hash()(key); +#endif + } +}; + +/// A template for hash_maps keyed by a const char* that is maintained within +/// the values. Use like: +/// ExternalStringHash::Type foos; +/// to make foos into a hash mapping const char* => Foo*. +template +struct ExternalStringHashMap { + typedef hash_map Type; +}; + #endif // NINJA_MAP_H_ diff --git a/src/stat_cache.cc b/src/stat_cache.cc index 487afd1..75248be 100644 --- a/src/stat_cache.cc +++ b/src/stat_cache.cc @@ -19,12 +19,11 @@ #include "graph.h" FileStat* StatCache::GetFile(const std::string& path) { - Key key(path.c_str()); - Paths::iterator i = paths_.find(key); + Paths::iterator i = paths_.find(path.c_str()); if (i != paths_.end()) return i->second; FileStat* file = new FileStat(path); - paths_[Key(file->path_.c_str())] = file; + paths_[file->path_.c_str()] = file; return file; } diff --git a/src/stat_cache.h b/src/stat_cache.h index 1b9a8ff..9cb3eff 100644 --- a/src/stat_cache.h +++ b/src/stat_cache.h @@ -31,27 +31,7 @@ struct StatCache { void Dump(); void Reload(); - struct Key { - Key() : path(NULL) {} - Key(const char* p) : path(p) {} - - const char* path; - bool operator==(const Key& other) const { - return strcmp(path, other.path) == 0; - } - }; - - struct KeyHash { - size_t operator()(const StatCache::Key& key) const { -#ifdef _MSC_VER - return stdext::hash()(key.path); -#else - return __gnu_cxx::hash()(key.path); -#endif - } - }; - - typedef hash_map Paths; + typedef ExternalStringHashMap::Type Paths; Paths paths_; }; -- cgit v0.12