Don't call NormalizePath in core indexing logic; syscall dominates indexing time

This commit is contained in:
Jacob Dufault 2017-04-12 00:04:06 -07:00
parent 33c91de4c0
commit 12a0db7d10
3 changed files with 55 additions and 17 deletions

View File

@ -1,36 +1,66 @@
#include "file_consumer.h" #include "file_consumer.h"
#include "indexer.h" #include "indexer.h"
#include "platform.h"
#include "utils.h" #include "utils.h"
namespace {
std::string FileName(CXFile file) {
CXString cx_name = clang_getFileName(file);
std::string name = clang::ToString(cx_name);
return NormalizePath(name);
}
} // namespace
bool operator==(const CXFileUniqueID& a, const CXFileUniqueID& b) {
return a.data[0] == b.data[0] && a.data[1] == b.data[1] && a.data[2] == b.data[2];
}
FileConsumer::FileConsumer(SharedState* shared_state) : shared_(shared_state) {} FileConsumer::FileConsumer(SharedState* shared_state) : shared_(shared_state) {}
IndexedFile* FileConsumer::TryConsumeFile(const std::string& file, bool* is_first_ownership) { IndexedFile* FileConsumer::TryConsumeFile(CXFile file, bool* is_first_ownership) {
assert(is_first_ownership); assert(is_first_ownership);
CXFileUniqueID file_id;
if (clang_getFileUniqueID(file, &file_id) != 0) {
std::cerr << "Could not get unique file id for " << FileName(file) << std::endl;
return nullptr;
}
// Try to find cached local result. // Try to find cached local result.
auto it = local_.find(file); auto it = local_.find(file_id);
if (it != local_.end()) { if (it != local_.end()) {
*is_first_ownership = false; *is_first_ownership = false;
return it->second.get(); return it->second.get();
} }
std::string file_name = FileName(file);
// No result in local; we need to query global. // No result in local; we need to query global.
bool did_insert = false; bool did_insert = false;
{ {
std::lock_guard<std::mutex> lock(shared_->mutex); std::lock_guard<std::mutex> lock(shared_->mutex);
did_insert = shared_->files.insert(file).second; did_insert = shared_->files.insert(file_name).second;
} }
*is_first_ownership = did_insert; *is_first_ownership = did_insert;
local_[file] = did_insert ? MakeUnique<IndexedFile>(file) : nullptr; local_[file_id] = did_insert ? MakeUnique<IndexedFile>(file_name) : nullptr;
return local_[file].get(); return local_[file_id].get();
} }
IndexedFile* FileConsumer::ForceLocal(const std::string& file) { IndexedFile* FileConsumer::ForceLocal(CXFile file) {
auto it = local_.find(file); CXFileUniqueID file_id;
if (clang_getFileUniqueID(file, &file_id) != 0) {
std::cerr << "Could not get unique file id for " << FileName(file) << std::endl;
return nullptr;
}
auto it = local_.find(file_id);
if (it == local_.end()) if (it == local_.end())
local_[file] = MakeUnique<IndexedFile>(file); local_[file_id] = MakeUnique<IndexedFile>(FileName(file));
return local_[file].get(); assert(local_.find(file_id) != local_.end());
return local_[file_id].get();
} }
std::vector<std::unique_ptr<IndexedFile>> FileConsumer::TakeLocalState() { std::vector<std::unique_ptr<IndexedFile>> FileConsumer::TakeLocalState() {

View File

@ -1,11 +1,20 @@
#pragma once #pragma once
#include "utils.h"
#include <clang-c/Index.h>
#include <functional>
#include <mutex> #include <mutex>
#include <unordered_set> #include <unordered_set>
#include <unordered_map> #include <unordered_map>
struct IndexedFile; struct IndexedFile;
// Needed for unordered_map usage below.
MAKE_HASHABLE(CXFileUniqueID, t.data[0], t.data[1], t.data[2]);
bool operator==(const CXFileUniqueID& a, const CXFileUniqueID& b);
// FileConsumer is used by the indexer. When it encouters a file, it tries to // FileConsumer is used by the indexer. When it encouters a file, it tries to
// take ownership over it. If the indexer has ownership over a file, it will // take ownership over it. If the indexer has ownership over a file, it will
// produce an index, otherwise, it will emit nothing for that declarations // produce an index, otherwise, it will emit nothing for that declarations
@ -27,15 +36,15 @@ struct FileConsumer {
// Returns IndexedFile for the file or nullptr. |is_first_ownership| is set // Returns IndexedFile for the file or nullptr. |is_first_ownership| is set
// to true iff the function just took ownership over the file. Otherwise it // to true iff the function just took ownership over the file. Otherwise it
// is set to false. // is set to false.
IndexedFile* TryConsumeFile(const std::string& file, bool* is_first_ownership); IndexedFile* TryConsumeFile(CXFile file, bool* is_first_ownership);
// Forcibly create a local file, even if it has already been parsed. // Forcibly create a local file, even if it has already been parsed.
IndexedFile* ForceLocal(const std::string& file); IndexedFile* ForceLocal(CXFile file);
// Returns and passes ownership of all local state. // Returns and passes ownership of all local state.
std::vector<std::unique_ptr<IndexedFile>> TakeLocalState(); std::vector<std::unique_ptr<IndexedFile>> TakeLocalState();
private: private:
std::unordered_map<std::string, std::unique_ptr<IndexedFile>> local_; std::unordered_map<CXFileUniqueID, std::unique_ptr<IndexedFile>> local_;
SharedState* shared_; SharedState* shared_;
}; };

View File

@ -711,10 +711,9 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
// TODO: Use clang_getFileUniqueID // TODO: Use clang_getFileUniqueID
CXFile file; CXFile file;
clang_getSpellingLocation(clang_indexLoc_getCXSourceLocation(decl->loc), &file, nullptr, nullptr, nullptr); clang_getSpellingLocation(clang_indexLoc_getCXSourceLocation(decl->loc), &file, nullptr, nullptr, nullptr);
std::string filename = NormalizePath(clang::ToString(clang_getFileName(file)));
IndexParam* param = static_cast<IndexParam*>(client_data); IndexParam* param = static_cast<IndexParam*>(client_data);
bool is_first_time_visiting_file = false; bool is_first_time_visiting_file = false;
IndexedFile* db = param->file_consumer->TryConsumeFile(filename, &is_first_time_visiting_file); IndexedFile* db = param->file_consumer->TryConsumeFile(file, &is_first_time_visiting_file);
if (!db) if (!db)
return; return;
@ -1170,10 +1169,9 @@ void indexEntityReference(CXClientData client_data,
// TODO: Use clang_getFileUniqueID // TODO: Use clang_getFileUniqueID
CXFile file; CXFile file;
clang_getSpellingLocation(clang_indexLoc_getCXSourceLocation(ref->loc), &file, nullptr, nullptr, nullptr); clang_getSpellingLocation(clang_indexLoc_getCXSourceLocation(ref->loc), &file, nullptr, nullptr, nullptr);
std::string filename = NormalizePath(clang::ToString(clang_getFileName(file)));
IndexParam* param = static_cast<IndexParam*>(client_data); IndexParam* param = static_cast<IndexParam*>(client_data);
bool is_first_time_visiting_file = false; bool is_first_time_visiting_file = false;
IndexedFile* db = param->file_consumer->TryConsumeFile(filename, &is_first_time_visiting_file); IndexedFile* db = param->file_consumer->TryConsumeFile(file, &is_first_time_visiting_file);
if (!db) if (!db)
return; return;
@ -1415,7 +1413,8 @@ std::vector<std::unique_ptr<IndexedFile>> Parse(FileConsumer* file_consumer, std
IndexParam param(file_consumer); IndexParam param(file_consumer);
param.primary_file = file_consumer->ForceLocal(filename); CXFile file = clang_getFile(tu.cx_tu, filename.c_str());
param.primary_file = file_consumer->ForceLocal(file);
std::cerr << "!! [START] Indexing " << filename << std::endl; std::cerr << "!! [START] Indexing " << filename << std::endl;
CXIndexAction index_action = clang_IndexAction_create(index.cx_index); CXIndexAction index_action = clang_IndexAction_create(index.cx_index);