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 "indexer.h"
#include "platform.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) {}
IndexedFile* FileConsumer::TryConsumeFile(const std::string& file, bool* is_first_ownership) {
IndexedFile* FileConsumer::TryConsumeFile(CXFile file, bool* 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.
auto it = local_.find(file);
auto it = local_.find(file_id);
if (it != local_.end()) {
*is_first_ownership = false;
return it->second.get();
}
std::string file_name = FileName(file);
// No result in local; we need to query global.
bool did_insert = false;
{
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;
local_[file] = did_insert ? MakeUnique<IndexedFile>(file) : nullptr;
return local_[file].get();
local_[file_id] = did_insert ? MakeUnique<IndexedFile>(file_name) : nullptr;
return local_[file_id].get();
}
IndexedFile* FileConsumer::ForceLocal(const std::string& file) {
auto it = local_.find(file);
IndexedFile* FileConsumer::ForceLocal(CXFile 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())
local_[file] = MakeUnique<IndexedFile>(file);
return local_[file].get();
local_[file_id] = MakeUnique<IndexedFile>(FileName(file));
assert(local_.find(file_id) != local_.end());
return local_[file_id].get();
}
std::vector<std::unique_ptr<IndexedFile>> FileConsumer::TakeLocalState() {

View File

@ -1,11 +1,20 @@
#pragma once
#include "utils.h"
#include <clang-c/Index.h>
#include <functional>
#include <mutex>
#include <unordered_set>
#include <unordered_map>
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
// 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
@ -27,15 +36,15 @@ struct FileConsumer {
// 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
// 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.
IndexedFile* ForceLocal(const std::string& file);
IndexedFile* ForceLocal(CXFile file);
// Returns and passes ownership of all local state.
std::vector<std::unique_ptr<IndexedFile>> TakeLocalState();
private:
std::unordered_map<std::string, std::unique_ptr<IndexedFile>> local_;
std::unordered_map<CXFileUniqueID, std::unique_ptr<IndexedFile>> local_;
SharedState* shared_;
};

View File

@ -711,10 +711,9 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
// TODO: Use clang_getFileUniqueID
CXFile file;
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);
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)
return;
@ -1170,10 +1169,9 @@ void indexEntityReference(CXClientData client_data,
// TODO: Use clang_getFileUniqueID
CXFile file;
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);
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)
return;
@ -1415,7 +1413,8 @@ std::vector<std::unique_ptr<IndexedFile>> Parse(FileConsumer* file_consumer, std
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;
CXIndexAction index_action = clang_IndexAction_create(index.cx_index);