From af520667caff8afcb815873531b237cfcc0e35f9 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Fri, 3 Mar 2023 10:40:01 +0100 Subject: [PATCH] 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: Reviewed-by: Cristian Adam --- src/plugins/terminal/scrollback.cpp | 31 ++++++++++++++++++++--------- src/plugins/terminal/scrollback.h | 6 ++++-- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/plugins/terminal/scrollback.cpp b/src/plugins/terminal/scrollback.cpp index c3be95f706c..6330e3c0ac7 100644 --- a/src/plugins/terminal/scrollback.cpp +++ b/src/plugins/terminal/scrollback.cpp @@ -7,14 +7,23 @@ #include #include +#include namespace Terminal::Internal { Scrollback::Line::Line(int cols, const VTermScreenCell *cells, VTermState *vts) : m_cols(cols) , m_cells(std::make_unique(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 diff --git a/src/plugins/terminal/scrollback.h b/src/plugins/terminal/scrollback.h index 22abc07b73f..4d8849182c9 100644 --- a/src/plugins/terminal/scrollback.h +++ b/src/plugins/terminal/scrollback.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -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 m_cells; mutable std::unique_ptr m_layout; mutable int m_layoutVersion{-1}; + mutable std::optional m_text; + mutable std::future m_textFuture; }; public: @@ -63,8 +67,6 @@ private: size_t m_capacity; size_t m_offset{0}; std::deque m_deque; - - std::u32string m_currentText; }; } // namespace Terminal::Internal