Terminal: Improve performance for cat /dev/random

Change-Id: Ibc7e09dd9388fd6f06f0bed3ade4e83d05f03c28
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
This commit is contained in:
Marcus Tillmanns
2023-03-01 10:48:05 +01:00
parent 86da87d306
commit 46ccaa642f
4 changed files with 42 additions and 24 deletions

View File

@@ -20,7 +20,6 @@ Scrollback::Line::Line(int cols, const VTermScreenCell *cells, VTermState *vts)
vterm_state_convert_color_to_rgb(vts, &m_cells[i].fg); vterm_state_convert_color_to_rgb(vts, &m_cells[i].fg);
vterm_state_convert_color_to_rgb(vts, &m_cells[i].bg); vterm_state_convert_color_to_rgb(vts, &m_cells[i].bg);
} }
m_layout = std::make_unique<QTextLayout>();
} }
const VTermScreenCell *Scrollback::Line::cell(int i) const const VTermScreenCell *Scrollback::Line::cell(int i) const
@@ -31,6 +30,9 @@ const VTermScreenCell *Scrollback::Line::cell(int i) const
const QTextLayout &Scrollback::Line::layout(int version, const QFont &font, qreal lineSpacing) const const QTextLayout &Scrollback::Line::layout(int version, const QFont &font, qreal lineSpacing) const
{ {
if (!m_layout)
m_layout = std::make_unique<QTextLayout>();
if (m_layoutVersion != version) { if (m_layoutVersion != version) {
QString text; QString text;
VTermColor defaultBg; VTermColor defaultBg;

View File

@@ -33,7 +33,7 @@ public:
private: private:
int m_cols; int m_cols;
std::unique_ptr<VTermScreenCell[]> m_cells; std::unique_ptr<VTermScreenCell[]> m_cells;
std::unique_ptr<QTextLayout> m_layout; mutable std::unique_ptr<QTextLayout> m_layout;
mutable int m_layoutVersion{-1}; mutable int m_layoutVersion{-1};
}; };

View File

@@ -29,6 +29,8 @@
#include <QScrollBar> #include <QScrollBar>
#include <QTextLayout> #include <QTextLayout>
#include <chrono>
Q_LOGGING_CATEGORY(terminalLog, "qtc.terminal", QtWarningMsg) Q_LOGGING_CATEGORY(terminalLog, "qtc.terminal", QtWarningMsg)
using namespace Utils; using namespace Utils;
@@ -36,6 +38,11 @@ using namespace Utils::Terminal;
namespace Terminal { namespace Terminal {
using namespace std::chrono_literals;
// Minimum time between two refreshes.
static const auto minRefreshInterval = 16ms;
TerminalWidget::TerminalWidget(QWidget *parent, const OpenTerminalParameters &openParameters) TerminalWidget::TerminalWidget(QWidget *parent, const OpenTerminalParameters &openParameters)
: QAbstractScrollArea(parent) : QAbstractScrollArea(parent)
, m_vterm(vterm_new(size().height(), size().width()), vterm_free) , m_vterm(vterm_new(size().height(), size().width()), vterm_free)
@@ -47,6 +54,7 @@ TerminalWidget::TerminalWidget(QWidget *parent, const OpenTerminalParameters &op
, m_zoomInAction(Tr::tr("Zoom In")) , m_zoomInAction(Tr::tr("Zoom In"))
, m_zoomOutAction(Tr::tr("Zoom Out")) , m_zoomOutAction(Tr::tr("Zoom Out"))
, m_openParameters(openParameters) , m_openParameters(openParameters)
, m_lastFlush(QDateTime::currentDateTime())
{ {
setupVTerm(); setupVTerm();
setupFont(); setupFont();
@@ -66,13 +74,10 @@ TerminalWidget::TerminalWidget(QWidget *parent, const OpenTerminalParameters &op
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
m_readDelayTimer.setSingleShot(true); m_flushDelayTimer.setSingleShot(true);
m_readDelayTimer.setInterval(10); m_flushDelayTimer.setInterval(minRefreshInterval);
connect(&m_readDelayTimer, &QTimer::timeout, this, [this] { connect(&m_flushDelayTimer, &QTimer::timeout, this, [this]() { flushVTerm(true); });
m_readDelayRestarts = 0;
onReadyRead();
});
connect(&m_copyAction, &QAction::triggered, this, &TerminalWidget::copyToClipboard); connect(&m_copyAction, &QAction::triggered, this, &TerminalWidget::copyToClipboard);
connect(&m_pasteAction, &QAction::triggered, this, &TerminalWidget::pasteFromClipboard); connect(&m_pasteAction, &QAction::triggered, this, &TerminalWidget::pasteFromClipboard);
@@ -109,14 +114,8 @@ void TerminalWidget::setupPty()
m_process->setWorkingDirectory(*m_openParameters.workingDirectory); m_process->setWorkingDirectory(*m_openParameters.workingDirectory);
m_process->setEnvironment(env); m_process->setEnvironment(env);
connect(m_process.get(), &QtcProcess::readyReadStandardOutput, this, [this] { connect(m_process.get(), &QtcProcess::readyReadStandardOutput, this, [this]() {
if (m_readDelayTimer.isActive()) onReadyRead(false);
m_readDelayRestarts++;
if (m_readDelayRestarts > 100)
return;
m_readDelayTimer.start();
}); });
connect(m_process.get(), &QtcProcess::done, this, [this] { connect(m_process.get(), &QtcProcess::done, this, [this] {
@@ -138,7 +137,9 @@ void TerminalWidget::setupPty()
} }
if (m_openParameters.m_exitBehavior == ExitBehavior::Restart) { if (m_openParameters.m_exitBehavior == ExitBehavior::Restart) {
QMetaObject::invokeMethod(this, [this] { QMetaObject::invokeMethod(
this,
[this] {
m_process.reset(); m_process.reset();
setupPty(); setupPty();
}, },
@@ -411,17 +412,29 @@ void TerminalWidget::clearContents()
// Fake a scrollback clearing // Fake a scrollback clearing
QByteArray data{"\x1b[3J"}; QByteArray data{"\x1b[3J"};
vterm_input_write(m_vterm.get(), data.constData(), data.size()); vterm_input_write(m_vterm.get(), data.constData(), data.size());
vterm_screen_flush_damage(m_vtermScreen);
// Send Ctrl+L which will clear the screen // Send Ctrl+L which will clear the screen
writeToPty(QByteArray("\f")); writeToPty(QByteArray("\f"));
} }
void TerminalWidget::onReadyRead() void TerminalWidget::onReadyRead(bool forceFlush)
{ {
QByteArray data = m_process->readAllRawStandardOutput(); QByteArray data = m_process->readAllRawStandardOutput();
vterm_input_write(m_vterm.get(), data.constData(), data.size()); vterm_input_write(m_vterm.get(), data.constData(), data.size());
flushVTerm(forceFlush);
}
void TerminalWidget::flushVTerm(bool force)
{
if (force || QDateTime::currentDateTime() - m_lastFlush > minRefreshInterval) {
m_lastFlush = QDateTime::currentDateTime();
vterm_screen_flush_damage(m_vtermScreen); vterm_screen_flush_damage(m_vtermScreen);
return;
}
if (!m_flushDelayTimer.isActive())
m_flushDelayTimer.start();
} }
const VTermScreenCell *TerminalWidget::fetchCell(int x, int y) const const VTermScreenCell *TerminalWidget::fetchCell(int x, int y) const
@@ -707,7 +720,7 @@ void TerminalWidget::applySizeChange()
m_process->ptyData().resize(m_vtermSize); m_process->ptyData().resize(m_vtermSize);
vterm_set_size(m_vterm.get(), m_vtermSize.height(), m_vtermSize.width()); vterm_set_size(m_vterm.get(), m_vtermSize.height(), m_vtermSize.width());
vterm_screen_flush_damage(m_vtermScreen); flushVTerm(true);
} }
void TerminalWidget::updateScrollBars() void TerminalWidget::updateScrollBars()

View File

@@ -76,7 +76,7 @@ protected:
bool event(QEvent *event) override; bool event(QEvent *event) override;
protected: protected:
void onReadyRead(); void onReadyRead(bool forceFlush);
void setupVTerm(); void setupVTerm();
void setupFont(); void setupFont();
void setupPty(); void setupPty();
@@ -110,6 +110,8 @@ protected:
void updateScrollBars(); void updateScrollBars();
void flushVTerm(bool force);
private: private:
std::unique_ptr<Utils::QtcProcess> m_process; std::unique_ptr<Utils::QtcProcess> m_process;
@@ -151,14 +153,15 @@ private:
QAction m_zoomInAction; QAction m_zoomInAction;
QAction m_zoomOutAction; QAction m_zoomOutAction;
QTimer m_readDelayTimer; QTimer m_flushDelayTimer;
int m_readDelayRestarts{0};
int m_layoutVersion{0}; int m_layoutVersion{0};
std::array<QColor, 18> m_currentColors; std::array<QColor, 18> m_currentColors;
Utils::Terminal::OpenTerminalParameters m_openParameters; Utils::Terminal::OpenTerminalParameters m_openParameters;
QDateTime m_lastFlush;
}; };
} // namespace Terminal } // namespace Terminal