mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-29 22:20:48 +00:00
logs: Batch log messages (optimization)
This commit is contained in:
parent
0bfdfd8433
commit
74a909cfbc
@ -79,7 +79,6 @@ struct gui_listener : logs::listener
|
|||||||
}
|
}
|
||||||
|
|
||||||
_new->msg += text;
|
_new->msg += text;
|
||||||
_new->msg += '\n';
|
|
||||||
|
|
||||||
queue.push(std::move(p));
|
queue.push(std::move(p));
|
||||||
}
|
}
|
||||||
@ -587,87 +586,153 @@ void log_frame::UpdateUI()
|
|||||||
const QString font_start_tag_stack = "<font color = \"" % m_color_stack.name() % "\">";
|
const QString font_start_tag_stack = "<font color = \"" % m_color_stack.name() % "\">";
|
||||||
const QString font_end_tag = QStringLiteral("</font>");
|
const QString font_end_tag = QStringLiteral("</font>");
|
||||||
|
|
||||||
static constexpr auto escaped = [](QString& text)
|
static constexpr auto escaped = [](const QString& text)
|
||||||
{
|
{
|
||||||
return text.toHtmlEscaped().replace(QStringLiteral("\n"), QStringLiteral("<br/>"));
|
return text.toHtmlEscaped().replace(QStringLiteral("\n"), QStringLiteral("<br/>"));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Preserve capacity
|
||||||
|
m_log_text.resize(0);
|
||||||
|
|
||||||
|
// Handle a special case in which we may need to override the previous repetition count
|
||||||
|
bool is_first_rep = true;
|
||||||
|
|
||||||
|
// Batch output of multiple lines if possible (optimization)
|
||||||
|
auto flush = [&]()
|
||||||
|
{
|
||||||
|
if (m_log_text.isEmpty() && !is_first_rep)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save old log state
|
||||||
|
QScrollBar* sb = m_log->verticalScrollBar();
|
||||||
|
const bool isMax = sb->value() == sb->maximum();
|
||||||
|
const int sb_pos = sb->value();
|
||||||
|
|
||||||
|
QTextCursor text_cursor = m_log->textCursor();
|
||||||
|
const int sel_pos = text_cursor.position();
|
||||||
|
int sel_start = text_cursor.selectionStart();
|
||||||
|
int sel_end = text_cursor.selectionEnd();
|
||||||
|
|
||||||
|
// clear selection or else it will get colorized as well
|
||||||
|
text_cursor.clearSelection();
|
||||||
|
|
||||||
|
m_log->setTextCursor(text_cursor);
|
||||||
|
|
||||||
|
if (is_first_rep)
|
||||||
|
{
|
||||||
|
// Override repetition count of previous UpdateUI() (special case)
|
||||||
|
text_cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
|
||||||
|
text_cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, (m_log_counter != 2 ? 1 + QString::number(m_log_counter - 1).size() : 0));
|
||||||
|
text_cursor.insertHtml(font_start_tag_stack % QStringLiteral(" x") % QString::number(m_log_counter) % font_end_tag);
|
||||||
|
}
|
||||||
|
else if (m_log_counter > 1)
|
||||||
|
{
|
||||||
|
// Insert both messages and repetition prefix (append is more optimized than concatenation)
|
||||||
|
m_log_text += font_end_tag;
|
||||||
|
m_log_text += font_start_tag_stack;
|
||||||
|
m_log_text += QStringLiteral(" x");
|
||||||
|
m_log_text += QString::number(m_log_counter);
|
||||||
|
m_log_text += font_end_tag;
|
||||||
|
|
||||||
|
m_log->appendHtml(m_log_text);
|
||||||
|
m_log_counter = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log_text += font_end_tag;
|
||||||
|
m_log->appendHtml(m_log_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we mark text from right to left we need to swap sides (start is always smaller than end)
|
||||||
|
if (sel_pos < sel_end)
|
||||||
|
{
|
||||||
|
std::swap(sel_start, sel_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset old text cursor and selection
|
||||||
|
text_cursor.setPosition(sel_start);
|
||||||
|
text_cursor.setPosition(sel_end, QTextCursor::KeepAnchor);
|
||||||
|
m_log->setTextCursor(text_cursor);
|
||||||
|
|
||||||
|
// set scrollbar to max means auto-scroll
|
||||||
|
sb->setValue(isMax ? sb->maximum() : sb_pos);
|
||||||
|
m_log_text.clear();
|
||||||
|
};
|
||||||
|
|
||||||
// Check main logs
|
// Check main logs
|
||||||
while (auto* packet = s_gui_listener.get())
|
while (auto* packet = s_gui_listener.get())
|
||||||
{
|
{
|
||||||
// Confirm log level
|
// Confirm log level
|
||||||
if (packet->sev <= s_gui_listener.enabled)
|
if (packet->sev <= s_gui_listener.enabled)
|
||||||
{
|
{
|
||||||
QString text;
|
if (m_stack_log && m_old_log_level == packet->sev && packet->msg == m_old_log_text)
|
||||||
switch (packet->sev)
|
|
||||||
{
|
{
|
||||||
case logs::level::always: text = QStringLiteral("- "); break;
|
m_log_counter++;
|
||||||
case logs::level::fatal: text = QStringLiteral("F "); break;
|
|
||||||
case logs::level::error: text = QStringLiteral("E "); break;
|
if (is_first_rep)
|
||||||
case logs::level::todo: text = QStringLiteral("U "); break;
|
{
|
||||||
case logs::level::success: text = QStringLiteral("S "); break;
|
flush();
|
||||||
case logs::level::warning: text = QStringLiteral("W "); break;
|
}
|
||||||
case logs::level::notice: text = QStringLiteral("! "); break;
|
|
||||||
case logs::level::trace: text = QStringLiteral("T "); break;
|
s_gui_listener.pop();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print UTF-8 text.
|
is_first_rep = false;
|
||||||
text += qstr(packet->msg);
|
|
||||||
|
|
||||||
// save old log state
|
if (m_log_counter > 1)
|
||||||
QScrollBar* sb = m_log->verticalScrollBar();
|
|
||||||
const bool isMax = sb->value() == sb->maximum();
|
|
||||||
const int sb_pos = sb->value();
|
|
||||||
|
|
||||||
QTextCursor text_cursor = m_log->textCursor();
|
|
||||||
const int sel_pos = text_cursor.position();
|
|
||||||
int sel_start = text_cursor.selectionStart();
|
|
||||||
int sel_end = text_cursor.selectionEnd();
|
|
||||||
|
|
||||||
// clear selection or else it will get colorized as well
|
|
||||||
text_cursor.clearSelection();
|
|
||||||
|
|
||||||
// remove the new line because Qt's append adds a new line already.
|
|
||||||
text.chop(1);
|
|
||||||
|
|
||||||
// create counter suffix and remove recurring line if needed
|
|
||||||
if (m_stack_log)
|
|
||||||
{
|
{
|
||||||
// add counter suffix if needed
|
// Add counter suffix if needed
|
||||||
if (text == m_old_log_text)
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_log_text.size() > 0x1000)
|
||||||
|
{
|
||||||
|
// Try not to hold too much data at a time so the frame content will be updated frequently
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_log_text.isEmpty())
|
||||||
|
{
|
||||||
|
if (packet->sev != m_old_log_level)
|
||||||
{
|
{
|
||||||
text_cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
|
flush();
|
||||||
text_cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor);
|
m_old_log_level = packet->sev;
|
||||||
text_cursor.insertHtml(font_start_tag(m_color[static_cast<int>(packet->sev)]) % escaped(text) % font_start_tag_stack % QStringLiteral(" x") % QString::number(++m_log_counter) % font_end_tag % font_end_tag);
|
m_log_text += font_start_tag(m_color[static_cast<int>(m_old_log_level)]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_log_counter = 1;
|
m_log_text += QStringLiteral("<br/>");
|
||||||
m_old_log_text = text;
|
|
||||||
|
|
||||||
m_log->setTextCursor(text_cursor);
|
|
||||||
m_log->appendHtml(font_start_tag(m_color[static_cast<int>(packet->sev)]) % escaped(text) % font_end_tag);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_log->setTextCursor(text_cursor);
|
m_old_log_level = packet->sev;
|
||||||
m_log->appendHtml(font_start_tag(m_color[static_cast<int>(packet->sev)]) % escaped(text) % font_end_tag);
|
m_log_text += font_start_tag(m_color[static_cast<int>(m_old_log_level)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we mark text from right to left we need to swap sides (start is always smaller than end)
|
switch (packet->sev)
|
||||||
if (sel_pos < sel_end)
|
|
||||||
{
|
{
|
||||||
std::swap(sel_start, sel_end);
|
case logs::level::always: m_log_text += QStringLiteral("- "); break;
|
||||||
|
case logs::level::fatal: m_log_text += QStringLiteral("F "); break;
|
||||||
|
case logs::level::error: m_log_text += QStringLiteral("E "); break;
|
||||||
|
case logs::level::todo: m_log_text += QStringLiteral("U "); break;
|
||||||
|
case logs::level::success: m_log_text += QStringLiteral("S "); break;
|
||||||
|
case logs::level::warning: m_log_text += QStringLiteral("W "); break;
|
||||||
|
case logs::level::notice: m_log_text += QStringLiteral("! "); break;
|
||||||
|
case logs::level::trace: m_log_text += QStringLiteral("T "); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset old text cursor and selection
|
// Print UTF-8 text.
|
||||||
text_cursor.setPosition(sel_start);
|
m_log_text += escaped(qstr(packet->msg));
|
||||||
text_cursor.setPosition(sel_end, QTextCursor::KeepAnchor);
|
|
||||||
m_log->setTextCursor(text_cursor);
|
|
||||||
|
|
||||||
// set scrollbar to max means auto-scroll
|
if (m_stack_log)
|
||||||
sb->setValue(isMax ? sb->maximum() : sb_pos);
|
{
|
||||||
|
m_log_counter = 1;
|
||||||
|
m_old_log_text = std::move(packet->msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drop packet
|
// Drop packet
|
||||||
@ -676,6 +741,9 @@ void log_frame::UpdateUI()
|
|||||||
// Limit processing time
|
// Limit processing time
|
||||||
if (steady_clock::now() >= start + 7ms) break;
|
if (steady_clock::now() >= start + 7ms) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_first_rep = false;
|
||||||
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_frame::closeEvent(QCloseEvent *event)
|
void log_frame::closeEvent(QCloseEvent *event)
|
||||||
|
@ -49,12 +49,14 @@ private:
|
|||||||
QList<QColor> m_color;
|
QList<QColor> m_color;
|
||||||
QColor m_color_stack;
|
QColor m_color_stack;
|
||||||
QPlainTextEdit* m_log = nullptr;
|
QPlainTextEdit* m_log = nullptr;
|
||||||
QString m_old_log_text;
|
std::string m_old_log_text;
|
||||||
QString m_old_tty_text;
|
QString m_old_tty_text;
|
||||||
|
QString m_log_text;
|
||||||
ullong m_log_counter{};
|
ullong m_log_counter{};
|
||||||
ullong m_tty_counter{};
|
ullong m_tty_counter{};
|
||||||
bool m_stack_log{};
|
bool m_stack_log{};
|
||||||
bool m_stack_tty{};
|
bool m_stack_tty{};
|
||||||
|
logs::level m_old_log_level{};
|
||||||
|
|
||||||
fs::file m_tty_file;
|
fs::file m_tty_file;
|
||||||
QWidget* m_tty_container = nullptr;
|
QWidget* m_tty_container = nullptr;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user