forked from qt-creator/qt-creator
Core: Adapt output window chunk size and queue timer dynamically
If we notice that our formatter takes longer to handle an incoming chunk of output than the amount of time we wait until we handle the next one, then we lower the chunk size and increase the interval. This way, we ensure responsiveness in the presence of excessive output. Task-number: QTCREATORBUG-30135 Change-Id: I1d1e31a7c6f26b50bdc048322e0f7987ddd7b317 Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -37,11 +37,15 @@
|
|||||||
|
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
|
||||||
const int chunkSize = 10000;
|
|
||||||
|
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
const int defaultChunkSize = 10000;
|
||||||
|
const int minChunkSize = 1000;
|
||||||
|
|
||||||
|
const auto defaultInterval = 10ms;
|
||||||
|
const auto maxInterval = 1000ms;
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -70,6 +74,7 @@ public:
|
|||||||
QTextCursor cursor;
|
QTextCursor cursor;
|
||||||
QString filterText;
|
QString filterText;
|
||||||
int lastFilteredBlockNumber = -1;
|
int lastFilteredBlockNumber = -1;
|
||||||
|
int chunkSize = defaultChunkSize;
|
||||||
QPalette originalPalette;
|
QPalette originalPalette;
|
||||||
OutputWindow::FilterModeFlags filterMode = OutputWindow::FilterModeFlag::Default;
|
OutputWindow::FilterModeFlags filterMode = OutputWindow::FilterModeFlag::Default;
|
||||||
int beforeContext = 0;
|
int beforeContext = 0;
|
||||||
@@ -97,7 +102,7 @@ OutputWindow::OutputWindow(Context context, const Key &settingsKey, QWidget *par
|
|||||||
d->formatter.setPlainTextEdit(this);
|
d->formatter.setPlainTextEdit(this);
|
||||||
|
|
||||||
d->queueTimer.setSingleShot(true);
|
d->queueTimer.setSingleShot(true);
|
||||||
d->queueTimer.setInterval(10ms);
|
d->queueTimer.setInterval(defaultInterval);
|
||||||
connect(&d->queueTimer, &QTimer::timeout, this, &OutputWindow::handleNextOutputChunk);
|
connect(&d->queueTimer, &QTimer::timeout, this, &OutputWindow::handleNextOutputChunk);
|
||||||
|
|
||||||
d->settingsKey = settingsKey;
|
d->settingsKey = settingsKey;
|
||||||
@@ -492,7 +497,7 @@ void OutputWindow::handleNextOutputChunk()
|
|||||||
|
|
||||||
// We want to break off the chunks along line breaks, if possible.
|
// We want to break off the chunks along line breaks, if possible.
|
||||||
// Otherwise we can get ugly temporary artifacts e.g. for ANSI escape codes.
|
// Otherwise we can get ugly temporary artifacts e.g. for ANSI escape codes.
|
||||||
int actualChunkSize = std::min(chunkSize, int(chunk.first.size()));
|
int actualChunkSize = std::min(d->chunkSize, int(chunk.first.size()));
|
||||||
const int minEndPos = std::max(0, actualChunkSize - 1000);
|
const int minEndPos = std::max(0, actualChunkSize - 1000);
|
||||||
for (int i = actualChunkSize - 1; i >= minEndPos; --i) {
|
for (int i = actualChunkSize - 1; i >= minEndPos; --i) {
|
||||||
if (chunk.first.at(i) == '\n') {
|
if (chunk.first.at(i) == '\n') {
|
||||||
@@ -544,7 +549,13 @@ void OutputWindow::handleOutputChunk(const QString &output, OutputFormat format)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QElapsedTimer formatterTimer;
|
||||||
|
formatterTimer.start();
|
||||||
d->formatter.appendMessage(out, format);
|
d->formatter.appendMessage(out, format);
|
||||||
|
if (formatterTimer.elapsed() > d->queueTimer.interval()) {
|
||||||
|
d->queueTimer.setInterval(std::min(maxInterval, d->queueTimer.intervalAsDuration() * 2));
|
||||||
|
d->chunkSize = std::max(minChunkSize, d->chunkSize / 2);
|
||||||
|
}
|
||||||
|
|
||||||
if (d->scrollToBottom) {
|
if (d->scrollToBottom) {
|
||||||
if (d->lastMessage.elapsed() < 5) {
|
if (d->lastMessage.elapsed() < 5) {
|
||||||
@@ -659,7 +670,7 @@ void OutputWindow::flush()
|
|||||||
{
|
{
|
||||||
const int totalQueuedSize = std::accumulate(d->queuedOutput.cbegin(), d->queuedOutput.cend(), 0,
|
const int totalQueuedSize = std::accumulate(d->queuedOutput.cbegin(), d->queuedOutput.cend(), 0,
|
||||||
[](int val, const QPair<QString, OutputFormat> &c) { return val + c.first.size(); });
|
[](int val, const QPair<QString, OutputFormat> &c) { return val + c.first.size(); });
|
||||||
if (totalQueuedSize > 5 * chunkSize) {
|
if (totalQueuedSize > 5 * d->chunkSize) {
|
||||||
d->flushRequested = true;
|
d->flushRequested = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user