Add index.trackDependency and improve pipeline

This commit is contained in:
Fangrui Song 2018-09-23 23:02:19 -07:00
parent d9541c3222
commit a3b982f5d7
3 changed files with 49 additions and 37 deletions

View File

@ -210,13 +210,13 @@ struct Config {
// May be too slow for big projects, so it is off by default. // May be too slow for big projects, so it is off by default.
bool onChange = false; bool onChange = false;
// Number of indexer threads. If 0, 80% of cores are used.
int threads = 0;
// Whether to reparse a file if write times of its dependencies have // Whether to reparse a file if write times of its dependencies have
// changed. The file will always be reparsed if its own write time changes. // changed. The file will always be reparsed if its own write time changes.
// 0: no, 1: only after initial load of project, 2: yes // 0: no, 1: only after initial load of project, 2: yes
int reparseForDependency = 2; int trackDependency = 2;
// Number of indexer threads. If 0, 80% of cores are used.
int threads = 0;
std::vector<std::string> whitelist; std::vector<std::string> whitelist;
} index; } index;
@ -256,7 +256,7 @@ MAKE_REFLECT_STRUCT(Config::Highlight, lsRanges, blacklist, whitelist)
MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, enabled, MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, enabled,
initialBlacklist, initialWhitelist, multiVersion, initialBlacklist, initialWhitelist, multiVersion,
multiVersionBlacklist, multiVersionWhitelist, onChange, multiVersionBlacklist, multiVersionWhitelist, onChange,
reparseForDependency, threads, whitelist); threads, trackDependency, whitelist);
MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort); MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort);
MAKE_REFLECT_STRUCT(Config::Xref, container, maxNum); MAKE_REFLECT_STRUCT(Config::Xref, container, maxNum);
MAKE_REFLECT_STRUCT(Config, compilationDatabaseCommand, MAKE_REFLECT_STRUCT(Config, compilationDatabaseCommand,

View File

@ -50,7 +50,8 @@ bool VFS::Stamp(const std::string &path, int64_t ts, int step) {
namespace ccls::pipeline { namespace ccls::pipeline {
int64_t loaded_ts = 0, tick = 0; std::atomic<int64_t> loaded_ts = ATOMIC_VAR_INIT(0);
int64_t tick = 0;
namespace { namespace {
@ -187,7 +188,7 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles,
if (!mtime1) if (!mtime1)
return true; return true;
if (vfs->Stamp(request.path, *mtime1, 0)) if (vfs->Stamp(request.path, *mtime1, 0))
reparse = 1; reparse = 2;
} }
if (g_config->index.onChange) { if (g_config->index.onChange) {
reparse = 2; reparse = 2;
@ -196,43 +197,53 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles,
if (request.path != path_to_index) if (request.path != path_to_index)
vfs->state[request.path].step = 0; vfs->state[request.path].step = 0;
} }
if (!reparse) bool track = g_config->index.trackDependency > 1 ||
(g_config->index.trackDependency == 1 && request.ts < loaded_ts);
if (!reparse && !track)
return true; return true;
if (reparse < 2) do { if (reparse < 2)
do {
std::unique_lock lock( std::unique_lock lock(
mutexes[std::hash<std::string>()(path_to_index) % N_MUTEXES]); mutexes[std::hash<std::string>()(path_to_index) % N_MUTEXES]);
prev = RawCacheLoad(path_to_index); prev = RawCacheLoad(path_to_index);
if (!prev || CacheInvalid(vfs, prev.get(), path_to_index, entry.args, if (!prev || CacheInvalid(vfs, prev.get(), path_to_index, entry.args,
std::nullopt)) std::nullopt))
break; break;
bool update = false; if (track)
for (const auto &dep : prev->dependencies) for (const auto &dep : prev->dependencies) {
if (auto mtime1 = LastWriteTime(dep.first.val().str())) { if (auto mtime1 = LastWriteTime(dep.first.val().str())) {
if (dep.second < *mtime1) if (dep.second < *mtime1) {
update = true; reparse = 2;
} else { break;
update = true;
} }
int forDep = g_config->index.reparseForDependency; } else {
if (update && (forDep > 1 || (forDep == 1 && request.ts < loaded_ts))) reparse = 2;
break;
}
}
if (reparse == 0)
return true;
if (reparse == 2)
break; break;
if (reparse < 2) {
LOG_S(INFO) << "load cache for " << path_to_index;
auto dependencies = prev->dependencies;
if (reparse) {
if (vfs->Loaded(path_to_index)) if (vfs->Loaded(path_to_index))
return true; return true;
LOG_S(INFO) << "load cache for " << path_to_index;
auto dependencies = prev->dependencies;
IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get());
on_indexed->PushBack(std::move(update), on_indexed->PushBack(std::move(update),
request.mode != IndexMode::NonInteractive); request.mode != IndexMode::NonInteractive);
{
std::lock_guard lock1(vfs->mutex); std::lock_guard lock1(vfs->mutex);
vfs->state[path_to_index].loaded = true; vfs->state[path_to_index].loaded = true;
} }
lock.unlock(); lock.unlock();
for (const auto &dep : dependencies) { for (const auto &dep : dependencies) {
std::string path = dep.first.val().str(); std::string path = dep.first.val().str();
if (!vfs->Stamp(path, dep.second, 1))
continue;
std::lock_guard lock1( std::lock_guard lock1(
mutexes[std::hash<std::string>()(path) % N_MUTEXES]); mutexes[std::hash<std::string>()(path) % N_MUTEXES]);
prev = RawCacheLoad(path); prev = RawCacheLoad(path);
@ -255,7 +266,6 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles,
} }
} }
return true; return true;
}
} while (0); } while (0);
LOG_IF_S(INFO, loud) << "parse " << path_to_index; LOG_IF_S(INFO, loud) << "parse " << path_to_index;

View File

@ -7,6 +7,7 @@
#include "method.h" #include "method.h"
#include "query.h" #include "query.h"
#include <atomic>
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
@ -41,7 +42,8 @@ enum class IndexMode {
}; };
namespace pipeline { namespace pipeline {
extern int64_t loaded_ts, tick; extern std::atomic<int64_t> loaded_ts;
extern int64_t tick;
void Init(); void Init();
void LaunchStdin(); void LaunchStdin();
void LaunchStdout(); void LaunchStdout();