optimize handleEvent() hot path
- Use QStringView to avoid string allocations during parsing
- Use QLatin1String for comparisons (faster than QString)
- Manual indexOf parsing instead of split('.') allocation
- Early return for non-session events
Reduces allocations in the agent.state hot path from ~7 QStrings
to 4 (only when state actually changes and needs to be stored).
This commit is contained in:
parent
249a19e261
commit
8792539bcc
|
|
@ -257,48 +257,70 @@ void Ollie9pClient::stopAgentConnections()
|
|||
}
|
||||
|
||||
// handleEvent processes a single event from eventwait.
|
||||
// Event format: "topic [payload]"
|
||||
// Topics: session.{sid}.{action}, session.{sid}.agent.{aid}.{action}
|
||||
// Event format: "topic payload" where topic is "session.{sid}.{action}" or
|
||||
// "session.{sid}.agent.{aid}.{action}"
|
||||
// Optimized for the hot path: agent.state changes
|
||||
void Ollie9pClient::handleEvent(const QString &eventLine)
|
||||
{
|
||||
if (eventLine.isEmpty()) return;
|
||||
|
||||
// Split into topic and payload
|
||||
int spaceIdx = eventLine.indexOf(' ');
|
||||
QString topic = spaceIdx > 0 ? eventLine.left(spaceIdx) : eventLine;
|
||||
QString payload = spaceIdx > 0 ? eventLine.mid(spaceIdx + 1) : QString();
|
||||
// Split topic and payload (avoid QString allocation where possible)
|
||||
const int spaceIdx = eventLine.indexOf(QLatin1Char(' '));
|
||||
const QStringView topic = spaceIdx > 0
|
||||
? QStringView(eventLine).left(spaceIdx)
|
||||
: QStringView(eventLine);
|
||||
const QStringView payload = spaceIdx > 0
|
||||
? QStringView(eventLine).mid(spaceIdx + 1)
|
||||
: QStringView();
|
||||
|
||||
QStringList parts = topic.split('.');
|
||||
// Expected: session.{sid}.* or session.{sid}.agent.{aid}.*
|
||||
// Fast path: must start with "session."
|
||||
if (!topic.startsWith(QLatin1String("session."))) return;
|
||||
|
||||
if (parts.size() >= 3 && parts[0] == "session") {
|
||||
QString sessionId = parts[1];
|
||||
QString action = parts[2];
|
||||
// Parse: session.{sid}.{rest...}
|
||||
const int firstDot = 7; // length of "session"
|
||||
const int secondDot = topic.indexOf(QLatin1Char('.'), firstDot + 1);
|
||||
if (secondDot < 0) return;
|
||||
|
||||
const QStringView sessionId = topic.mid(firstDot + 1, secondDot - firstDot - 1);
|
||||
const QStringView rest = topic.mid(secondDot + 1);
|
||||
|
||||
// Check for agent events: "agent.{aid}.{action}"
|
||||
if (rest.startsWith(QLatin1String("agent."))) {
|
||||
// Parse agent.{aid}.{action}
|
||||
const int agentDot = 5; // length of "agent"
|
||||
const int aidEnd = rest.indexOf(QLatin1Char('.'), agentDot + 1);
|
||||
if (aidEnd < 0) return;
|
||||
|
||||
if (action == "agent" && parts.size() >= 5) {
|
||||
// Agent event: session.{sid}.agent.{aid}.{action}
|
||||
QString agentId = parts[3];
|
||||
QString agentAction = parts[4];
|
||||
QString key = agentKey(sessionId, agentId);
|
||||
const QStringView agentId = rest.mid(agentDot + 1, aidEnd - agentDot - 1);
|
||||
const QStringView agentAction = rest.mid(aidEnd + 1);
|
||||
|
||||
if (agentAction == QLatin1String("state")) {
|
||||
// Hot path: agent state change
|
||||
if (payload.isEmpty()) return;
|
||||
|
||||
if (agentAction == "state") {
|
||||
// Update cached state
|
||||
if (!payload.isEmpty() && m_agentStateValues.value(key) != payload) {
|
||||
m_agentStateValues[key] = payload;
|
||||
emit agentStateChanged(sessionId, agentId, payload);
|
||||
// Also update activeState if this is the active agent
|
||||
if (sessionId == m_activeSessionId && agentId == m_agentId) {
|
||||
m_activeState = payload;
|
||||
emit activeStateChanged();
|
||||
}
|
||||
const QString sidStr = sessionId.toString();
|
||||
const QString aidStr = agentId.toString();
|
||||
const QString key = agentKey(sidStr, aidStr);
|
||||
const QString payloadStr = payload.toString();
|
||||
|
||||
if (m_agentStateValues.value(key) != payloadStr) {
|
||||
m_agentStateValues[key] = payloadStr;
|
||||
emit agentStateChanged(sidStr, aidStr, payloadStr);
|
||||
|
||||
// Fast check: is this the active agent?
|
||||
if (sidStr == m_activeSessionId && aidStr == m_agentId) {
|
||||
m_activeState = payloadStr;
|
||||
emit activeStateChanged();
|
||||
}
|
||||
} else if (agentAction == "new" || agentAction == "kill") {
|
||||
// Structural change — need full refresh
|
||||
refreshSessions();
|
||||
}
|
||||
} else if (action == "pause" || action == "resume" ||
|
||||
action == "new" || action == "kill" || action == "rename") {
|
||||
// Session-level structural change — need full refresh
|
||||
} else if (agentAction == QLatin1String("new") || agentAction == QLatin1String("kill")) {
|
||||
refreshSessions();
|
||||
}
|
||||
} else {
|
||||
// Session-level event
|
||||
if (rest == QLatin1String("pause") || rest == QLatin1String("resume") ||
|
||||
rest == QLatin1String("new") || rest == QLatin1String("kill") ||
|
||||
rest == QLatin1String("rename")) {
|
||||
refreshSessions();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Reference in New Issue