GitGrep: Use QStringView for parsing

This speeds up the parsing of big results (~2 million hits)
by ~5-10%.

Remove PromiseType alias.

Make regexp a member field and configure it just once inside c'tor.

Change-Id: Ib99597a7b8b979d49f36f2c7d146beeaa1caa380
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
Jarek Kobus
2023-06-01 18:24:51 +02:00
parent 71d492ae13
commit 738d13cd43

View File

@@ -25,7 +25,6 @@
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QRegularExpressionValidator> #include <QRegularExpressionValidator>
#include <QSettings> #include <QSettings>
#include <QTextStream>
using namespace Core; using namespace Core;
using namespace Utils; using namespace Utils;
@@ -43,10 +42,21 @@ public:
QString id() const { return recurseSubmodules ? ref + ".Rec" : ref; } QString id() const { return recurseSubmodules ? ref + ".Rec" : ref; }
}; };
static QStringView nextLine(QStringView *remainingInput)
{
const int newLinePos = remainingInput->indexOf('\n');
if (newLinePos < 0) {
QStringView ret = *remainingInput;
*remainingInput = QStringView();
return ret;
}
QStringView ret = remainingInput->left(newLinePos);
*remainingInput = remainingInput->mid(newLinePos + 1);
return ret;
}
class GitGrepRunner class GitGrepRunner
{ {
using PromiseType = QPromise<SearchResultItems>;
public: public:
GitGrepRunner(const TextEditor::FileFindParameters &parameters) GitGrepRunner(const TextEditor::FileFindParameters &parameters)
: m_parameters(parameters) : m_parameters(parameters)
@@ -54,6 +64,14 @@ public:
m_directory = FilePath::fromString(parameters.additionalParameters.toString()); m_directory = FilePath::fromString(parameters.additionalParameters.toString());
m_vcsBinary = GitClient::instance()->vcsBinary(); m_vcsBinary = GitClient::instance()->vcsBinary();
m_environment = GitClient::instance()->processEnvironment(); m_environment = GitClient::instance()->processEnvironment();
if (m_parameters.flags & FindRegularExpression) {
const QRegularExpression::PatternOptions patternOptions
= m_parameters.flags & FindCaseSensitively
? QRegularExpression::NoPatternOption
: QRegularExpression::CaseInsensitiveOption;
m_regexp.setPattern(m_parameters.text);
m_regexp.setPatternOptions(patternOptions);
}
} }
struct Match struct Match
@@ -67,7 +85,7 @@ public:
QStringList regexpCapturedTexts; QStringList regexpCapturedTexts;
}; };
void processLine(const QString &line, SearchResultItems *resultList) const void processLine(QStringView line, SearchResultItems *resultList) const
{ {
if (line.isEmpty()) if (line.isEmpty())
return; return;
@@ -75,23 +93,15 @@ public:
static const QLatin1String resetColor("\x1b[m"); static const QLatin1String resetColor("\x1b[m");
SearchResultItem result; SearchResultItem result;
const int lineSeparator = line.indexOf(QChar::Null); const int lineSeparator = line.indexOf(QChar::Null);
QString filePath = line.left(lineSeparator); QStringView filePath = line.left(lineSeparator);
if (!m_ref.isEmpty() && filePath.startsWith(m_ref)) if (!m_ref.isEmpty() && filePath.startsWith(m_ref))
filePath.remove(0, m_ref.length()); filePath = filePath.mid(m_ref.length());
result.setFilePath(m_directory.pathAppended(filePath)); result.setFilePath(m_directory.pathAppended(filePath.toString()));
const int textSeparator = line.indexOf(QChar::Null, lineSeparator + 1); const int textSeparator = line.indexOf(QChar::Null, lineSeparator + 1);
const int lineNumber = line.mid(lineSeparator + 1, textSeparator - lineSeparator - 1).toInt(); const int lineNumber = line.mid(lineSeparator + 1, textSeparator - lineSeparator - 1).toInt();
QString text = line.mid(textSeparator + 1); QString text = line.mid(textSeparator + 1).toString();
QRegularExpression regexp;
QList<Match> matches; QList<Match> matches;
if (m_parameters.flags & FindRegularExpression) { while (true) {
const QRegularExpression::PatternOptions patternOptions =
(m_parameters.flags & FindCaseSensitively)
? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption;
regexp.setPattern(m_parameters.text);
regexp.setPatternOptions(patternOptions);
}
for (;;) {
const int matchStart = text.indexOf(boldRed); const int matchStart = text.indexOf(boldRed);
if (matchStart == -1) if (matchStart == -1)
break; break;
@@ -102,7 +112,7 @@ public:
Match match(matchStart, matchLength); Match match(matchStart, matchLength);
const QString matchText = text.mid(matchTextStart, matchLength); const QString matchText = text.mid(matchTextStart, matchLength);
if (m_parameters.flags & FindRegularExpression) if (m_parameters.flags & FindRegularExpression)
match.regexpCapturedTexts = regexp.match(matchText).capturedTexts(); match.regexpCapturedTexts = m_regexp.match(matchText).capturedTexts();
matches.append(match); matches.append(match);
text = text.left(matchStart) + matchText + text.mid(matchEnd + resetColor.size()); text = text.left(matchStart) + matchText + text.mid(matchEnd + resetColor.size());
} }
@@ -116,18 +126,28 @@ public:
} }
} }
void read(PromiseType &fi, const QString &text) void read(QPromise<SearchResultItems> &promise, const QString &input)
{ {
SearchResultItems resultList; SearchResultItems items;
QString t = text; QStringView remainingInput(input);
QTextStream stream(&t); while (true) {
while (!stream.atEnd() && !fi.isCanceled()) if (promise.isCanceled())
processLine(stream.readLine(), &resultList); return;
if (!resultList.isEmpty() && !fi.isCanceled())
fi.addResult(resultList); if (remainingInput.isEmpty())
break;
const QStringView line = nextLine(&remainingInput);
if (line.isEmpty())
continue;
processLine(line, &items);
}
if (!items.isEmpty())
promise.addResult(items);
} }
void operator()(PromiseType &promise) void operator()(QPromise<SearchResultItems> &promise)
{ {
QStringList arguments = { QStringList arguments = {
"-c", "color.grep.match=bold red", "-c", "color.grep.match=bold red",
@@ -189,6 +209,7 @@ private:
QString m_ref; QString m_ref;
TextEditor::FileFindParameters m_parameters; TextEditor::FileFindParameters m_parameters;
Environment m_environment; Environment m_environment;
QRegularExpression m_regexp;
}; };
static bool isGitDirectory(const FilePath &path) static bool isGitDirectory(const FilePath &path)