diff options
author | Evan Martin <martine@danga.com> | 2011-09-12 18:44:12 (GMT) |
---|---|---|
committer | Evan Martin <martine@danga.com> | 2011-09-12 18:46:18 (GMT) |
commit | 3fbb25b2cc66f236a39b728d20e5d44da23612ac (patch) | |
tree | d6eb7c1bc63ef3d4d4d1056750756dc581da5ef0 /src | |
parent | f1139aff5deddacd899be064fad9ed5a185e7444 (diff) | |
download | Ninja-3fbb25b2cc66f236a39b728d20e5d44da23612ac.zip Ninja-3fbb25b2cc66f236a39b728d20e5d44da23612ac.tar.gz Ninja-3fbb25b2cc66f236a39b728d20e5d44da23612ac.tar.bz2 |
generalize the pattern of hash_map<const char*, ...>, 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.
Diffstat (limited to 'src')
-rw-r--r-- | src/build_log.cc | 14 | ||||
-rw-r--r-- | src/build_log.h | 4 | ||||
-rw-r--r-- | src/hash_map.h | 29 | ||||
-rw-r--r-- | src/stat_cache.cc | 5 | ||||
-rw-r--r-- | 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<Node*>::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 <string> 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<string, LogEntry*> Log; + typedef ExternalStringHashMap<LogEntry*>::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 <string.h> + #ifdef _MSC_VER #include <hash_map> @@ -37,4 +39,31 @@ struct hash<std::string> { #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<const char*>()(key); +#else + return __gnu_cxx::hash<const char*>()(key); +#endif + } +}; + +/// A template for hash_maps keyed by a const char* that is maintained within +/// the values. Use like: +/// ExternalStringHash<Foo*>::Type foos; +/// to make foos into a hash mapping const char* => Foo*. +template<typename V> +struct ExternalStringHashMap { + typedef hash_map<const char*, V, ExternalStringHash, ExternalStringEq> 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<const char*>()(key.path); -#else - return __gnu_cxx::hash<const char*>()(key.path); -#endif - } - }; - - typedef hash_map<Key, FileStat*, KeyHash> Paths; + typedef ExternalStringHashMap<FileStat*>::Type Paths; Paths paths_; }; |