Terminal: Defer scrollback text calculation

In high load situations, the conversion of cells to std::u32string's can
become a bottleneck. To address this, the calculation is deferred until
it is needed.

Change-Id: I0cc3c941fa680d8b9ebc3a5cba13cdc5c2db50f9
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
This commit is contained in:
Marcus Tillmanns
2023-03-03 10:40:01 +01:00
committed by Cristian Adam
parent dc4ec494b3
commit af520667ca
2 changed files with 26 additions and 11 deletions

View File

@@ -7,14 +7,23 @@
#include <cassert>
#include <cstring>
#include <future>
namespace Terminal::Internal {
Scrollback::Line::Line(int cols, const VTermScreenCell *cells, VTermState *vts)
: m_cols(cols)
, m_cells(std::make_unique<VTermScreenCell[]>(cols))
{
m_textFuture = std::async(std::launch::async, [this, cols] {
std::u32string text;
text.reserve(cols);
for (int i = 0; i < cols; ++i) {
text += cellToString(m_cells[i]);
}
return text;
});
memcpy(m_cells.get(), cells, cols * sizeof(cells[0]));
for (int i = 0; i < cols; ++i) {
vterm_state_convert_color_to_rgb(vts, &m_cells[i].fg);
@@ -49,6 +58,13 @@ const QTextLayout &Scrollback::Line::layout(int version, const QFont &font, qrea
return *m_layout;
}
const std::u32string &Scrollback::Line::text() const
{
if (!m_text)
m_text = m_textFuture.get();
return *m_text;
}
Scrollback::Scrollback(size_t capacity)
: m_capacity(capacity)
{}
@@ -57,13 +73,8 @@ void Scrollback::emplace(int cols, const VTermScreenCell *cells, VTermState *vts
{
m_deque.emplace_front(cols, cells, vts);
while (m_deque.size() > m_capacity) {
m_currentText = m_currentText.substr(m_deque.back().cols());
m_deque.pop_back();
}
for (int i = 0; i < cols; i++) {
m_currentText += cellToString(cells[i]);
}
}
void Scrollback::popto(int cols, VTermScreenCell *cells)
@@ -82,7 +93,6 @@ void Scrollback::popto(int cols, VTermScreenCell *cells)
}
m_deque.pop_front();
m_currentText.resize(m_currentText.size() - cols);
}
size_t Scrollback::scroll(int delta)
@@ -96,12 +106,15 @@ void Scrollback::clear()
{
m_offset = 0;
m_deque.clear();
m_currentText.clear();
}
std::u32string Scrollback::currentText()
{
return m_currentText;
std::u32string currentText;
for (auto it = m_deque.rbegin(); it != m_deque.rend(); ++it) {
currentText += it->text();
}
return currentText;
}
} // namespace Terminal::Internal

View File

@@ -7,6 +7,7 @@
#include <vterm.h>
#include <deque>
#include <future>
#include <memory>
#include <QFont>
@@ -29,12 +30,15 @@ public:
const VTermScreenCell *cells() const { return &m_cells[0]; };
const QTextLayout &layout(int version, const QFont &font, qreal lineSpacing) const;
const std::u32string &text() const;
private:
int m_cols;
std::unique_ptr<VTermScreenCell[]> m_cells;
mutable std::unique_ptr<QTextLayout> m_layout;
mutable int m_layoutVersion{-1};
mutable std::optional<std::u32string> m_text;
mutable std::future<std::u32string> m_textFuture;
};
public:
@@ -63,8 +67,6 @@ private:
size_t m_capacity;
size_t m_offset{0};
std::deque<Line> m_deque;
std::u32string m_currentText;
};
} // namespace Terminal::Internal