Skip to content

Commit

Permalink
高速化
Browse files Browse the repository at this point in the history
  • Loading branch information
soramimi committed Jan 19, 2024
1 parent 64e4b98 commit 19680b8
Show file tree
Hide file tree
Showing 14 changed files with 644 additions and 516 deletions.
167 changes: 107 additions & 60 deletions src/CommitDetailGetter.cpp
Original file line number Diff line number Diff line change
@@ -1,117 +1,164 @@
#include "CommitDetailGetter.h"
#include "ApplicationGlobal.h"

CommitDetailGetter::~CommitDetailGetter()
{
stop();
}

/**
* @brief CommitDetailGetter::start
* @param git
*
* コミットの詳細情報を取得するためのスレッドを開始する
*/
void CommitDetailGetter::start(GitPtr git)
{
interrupted_ = false;
stop();
git_ = git;
thread_ = std::make_shared<std::thread>([&](){
while (1) {
Item item;
{
std::unique_lock lock(mutex_);
if (interrupted_) return;
condition_.wait(lock);
if (interrupted_) return;
for (size_t i = 0; i < requests_.size(); i++) {
if (!requests_[i].done && !requests_[i].busy) {
requests_[i].busy = true;
item = requests_[i];
break;
threads_.clear();
threads_.resize(4);
for (int i = 0; i < threads_.size(); i++) {
std::thread th([&](){
while (1) {
Request item;
{
std::unique_lock lock(mutex_);
if (interrupted_) return;

auto NextQuery = [&](){
for (size_t i = requests_.size(); i > 0; i--) {
Request *r = &requests_[i - 1];
if (!r->done && !r->busy) {
r->busy = true;
item = *r;
break;
}
}
};

NextQuery();
if (!item.id) {
condition_.wait(lock);
if (interrupted_) return;
NextQuery();
}
}
}
if (item.id) {
auto c = git_->log_signature(item.id);
if (c) {
bool ok = false;
Git::CommitItem const &commit = *c;
item.value = commit.sign.verify;
if (item.id) {
auto c = git_->log_signature(item.id);
if (c) {
Git::CommitItem const &commit = *c;
item.data.sign_verify = commit.sign.verify;
}
item.done = true;
item.busy = false;
bool em = false;
{
std::lock_guard lock(mutex_);
if (interrupted_) return;
for (size_t i = 0; i < requests_.size(); i++) {
if (item.id == requests_[i].id) {
requests_.erase(requests_.begin() + i);
requests_.push_back(item);
requests_[i] = item;
ok = true;
cache_[item.id] = item.data;
em = true;
break;
}
}
}
if (ok) {
if (em) {
emit ready();
}
}
}
}
});
});
threads_[i] = std::move(th);
}
}

/**
* @brief CommitDetailGetter::stop
*
* スレッドを停止する
*/
void CommitDetailGetter::stop()
{
{
std::lock_guard lock(mutex_);
interrupted_ = true;
condition_.notify_all();
requests_.clear();
cache_.clear();
}
if (thread_) {
if (thread_->joinable()) {
thread_->join();
for (int i = 0; i < threads_.size(); i++) {
if (threads_[i].joinable()) {
threads_[i].join();
}
thread_.reset();
}
threads_.clear();
interrupted_ = false;
}

CommitDetailGetter::Item CommitDetailGetter::request(Git::CommitID id)
/**
* @brief CommitDetailGetter::query
* @param id
* @param request_if_not_found
* @param lock
* @return
*
* コミットの詳細情報を取得する
* 情報が存在しない場合はリクエスト予約を行う
*/
CommitDetailGetter::Data CommitDetailGetter::query(Git::CommitID const &id, bool request_if_not_found, bool lock)
{
if (lock) {
std::lock_guard l(mutex_);
return query(id, request_if_not_found, false);
}
if (id.isValid()) {
std::lock_guard lock(mutex_);
for (size_t i = 0; i < requests_.size(); i++) {
if (id == requests_[i].id) {
if (requests_[i].done) {
Item item = requests_[i];
auto it = cache_.find(id);
if (it != cache_.end()) {
return it->second;
}

if (request_if_not_found) {
for (size_t i = 0; i < requests_.size(); i++) {
auto item = requests_[i];
if (item.id == id) {
requests_.erase(requests_.begin() + i);
requests_.push_back(item);
return item;
if (item.done) {
cache_[item.id] = item.data;
return item.data;
}
return {};
}
}
}

Item item;
item.id = id;
requests_.push_back(item);
Request item;
item.id = id;
requests_.push_back(item);

size_t n = requests_.size();
if (n > 100) {
n -= 100;
requests_.erase(requests_.begin(), requests_.begin() + n);
}
const int MAX = std::min(1000, global->appsettings.maximum_number_of_commit_item_acquisitions);

condition_.notify_all();
}
return {};
}
size_t n = requests_.size();
if (n > MAX) {
n -= MAX;

void CommitDetailGetter::apply(Git::CommitItemList *logs)
{
std::lock_guard lock(mutex_);
for (size_t i = 0; i < requests_.size(); i++) {
if (requests_[i].done) {
Git::CommitID const &id = requests_[i].id;
for (size_t j = 0; j < logs->size(); j++) {
if (id == (*logs)[j].commit_id) {
(*logs)[j].sign.verify = requests_[i].value;
break;
for (size_t i = 0; i < n; i++) {
auto it = cache_.find(requests_[i].id);
if (it != cache_.end()) {
cache_.erase(it);
}
}

requests_.erase(requests_.begin(), requests_.begin() + n);
}

condition_.notify_all();
}
}
return {};
}


23 changes: 14 additions & 9 deletions src/CommitDetailGetter.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,41 @@
#include <memory>
#include <mutex>
#include <thread>
#include <map>

class CommitDetailGetter : public QObject {
Q_OBJECT
public:
struct Data {
char sign_verify = 0;
};
private:
std::mutex mutex_;
std::condition_variable condition_;
std::shared_ptr<std::thread> thread_;
std::vector<std::thread> threads_;
bool interrupted_ = false;

struct Item {
GitPtr git_;

struct Request {
bool done = false;
bool busy = false;
Git::CommitID id;
int value = 0;
Data data;

operator bool () const
{
return done;
}
};
std::vector<Item> requests_;

GitPtr git_;

std::vector<Request> requests_;
std::map<Git::CommitID, Data> cache_;
public:
CommitDetailGetter() = default;
virtual ~CommitDetailGetter();
void start(GitPtr git);
void stop();
CommitDetailGetter::Item request(Git::CommitID id);
void apply(Git::CommitItemList *logs);
Data query(const Git::CommitID &id, bool request_if_not_found, bool lock);
signals:
void ready();
};
Expand Down
23 changes: 6 additions & 17 deletions src/Git.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@
#include <set>
#include <optional>

#define DEBUGLOG 0



Git::CommitID::CommitID(const QString &qid)
{
assign(qid);
Expand Down Expand Up @@ -254,11 +250,10 @@ bool Git::git_(QString const &arg, bool chdir, bool log, bool errout, AbstractPt
qDebug() << "Invalid git command: " << gitCommand();
return false;
}
#if DEBUGLOG
qDebug() << "exec: git " << arg;
QTime timer;
timer.start();
#endif

QElapsedTimer _timer;
_timer.start();

clearResult();

QString env;
Expand Down Expand Up @@ -321,9 +316,7 @@ bool Git::git_(QString const &arg, bool chdir, bool log, bool errout, AbstractPt
ok = DoIt();
}

#if DEBUGLOG
qDebug() << timer.elapsed() << "ms";
#endif
// qDebug() << _timer.elapsed() << "ms";

return ok;
}
Expand Down Expand Up @@ -629,9 +622,6 @@ QList<Git::Branch> Git::branches()
QList<BranchItem> branches;
git(QString("branch -vv -a --abbrev=%1").arg(GIT_ID_LENGTH));
QString s = resultQString();
#if DEBUGLOG
qDebug() << s;
#endif

QStringList lines = misc::splitLines(s);
for (QString const &line : lines) {
Expand Down Expand Up @@ -755,7 +745,6 @@ std::optional<Git::CommitItem> Git::parseCommitItem(QString const &line)
item.commit_id = val;
} else if (key == "gpg") { // %G? 署名検証結果
item.sign.verify = *val.utf16();
item.sign.sg = Git::evaluateSignature(item.sign.verify);
} else if (key == "key") { // %GF 署名フィンガープリント
sign_fp = val.toStdString();
} else if (key == "trust") {
Expand Down Expand Up @@ -812,7 +801,7 @@ Git::CommitItemList Git::log_all(CommitID const &id, int maxcount)
for (QString const &line : lines) {
auto item = parseCommitItem(line);
if (item) {
items.push_back(*item);
items.list.push_back(*item);
}
}
}
Expand Down
Loading

0 comments on commit 19680b8

Please # to comment.