Module: check_mk
Branch: master
Commit: 91bc9c0be96eb1137f6bde204edc57adb532e538
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=91bc9c0be96eb1…
Author: Sven Panne <sp(a)mathias-kettner.de>
Date: Wed Aug 2 14:13:19 2017 +0200
Avoid unnecessary string copies.
The code is a bit more verbose than usual, but parsing the monitoring
history is a bit performance-sensitive.
Change-Id: I8498651adade98174d81ec011327dc11a449a6c2
---
livestatus/src/LogEntry.cc | 58 ++++++++++++++++++++++++++--------------------
livestatus/src/LogEntry.h | 6 +++--
livestatus/src/TableLog.cc | 2 +-
3 files changed, 38 insertions(+), 28 deletions(-)
diff --git a/livestatus/src/LogEntry.cc b/livestatus/src/LogEntry.cc
index c59d059..91a58f4 100644
--- a/livestatus/src/LogEntry.cc
+++ b/livestatus/src/LogEntry.cc
@@ -28,12 +28,14 @@
#include <unordered_map>
#include <utility>
#include "MonitoringCore.h"
-#include "StringUtils.h"
-using mk::starts_with;
using std::string;
using std::unordered_map;
+// 0123456789012345678901234567890
+// [1234567890] FOO BAR: blah blah
+static constexpr size_t timestamp_prefix_length = 13;
+
// TODO(sp) Fix classifyLogMessage() below to always set all fields and remove
// this set-me-to-zero-to-be-sure-block.
LogEntry::LogEntry(MonitoringCore *mc, unsigned lineno, string line)
@@ -54,9 +56,6 @@ LogEntry::LogEntry(MonitoringCore *mc, unsigned lineno, string line)
}
_options = &_complete[pos];
- // 0123456789012345678901234567890
- // [1234567890] FOO BAR: blah blah
- constexpr size_t timestamp_prefix_length = 13;
try {
if (_complete.size() < timestamp_prefix_length || _complete[0] != '['
||
_complete[11] != ']' || _complete[12] != ' ') {
@@ -69,7 +68,7 @@ LogEntry::LogEntry(MonitoringCore *mc, unsigned lineno, string line)
return; // ignore invalid lines silently
}
- classifyLogMessage(&_complete[timestamp_prefix_length]);
+ classifyLogMessage();
applyWorkarounds();
updateReferences(mc);
}
@@ -263,51 +262,52 @@ std::vector<LogEntry::LogDef> LogEntry::log_definitions //
NOLINT
////////////////
LogDef{"EXTERNAL COMMAND", Class::ext_command, LogEntryType::none, {}}};
-void LogEntry::classifyLogMessage(const string &text) {
+// A bit verbose, but we avoid unnecessary string copies below.
+void LogEntry::classifyLogMessage() {
for (const auto &def : log_definitions) {
- if (starts_with(text, def.prefix) &&
- text.compare(def.prefix.size(), 2, ": ") == 0) {
- _text = def.prefix;
+ if (textStartsWith(def.prefix) &&
+ _complete.compare(timestamp_prefix_length + def.prefix.size(), 2,
+ ": ") == 0) {
+ _text = &def.prefix[0];
_logclass = def.log_class;
_type = def.log_type;
// TODO(sp) Use boost::tokenizer instead of this index fiddling
- size_t pos = def.prefix.size() + 2;
+ size_t pos = timestamp_prefix_length + def.prefix.size() + 2;
for (Param par : def.params) {
- size_t sep_pos = text.find(';', pos);
+ size_t sep_pos = _complete.find(';', pos);
size_t end_pos =
- sep_pos == string::npos ? text.size() : sep_pos;
- assign(par, text.substr(pos, end_pos - pos));
- pos = sep_pos == string::npos ? text.size() : (sep_pos + 1);
+ sep_pos == string::npos ? _complete.size() : sep_pos;
+ assign(par, _complete.substr(pos, end_pos - pos));
+ pos =
+ sep_pos == string::npos ? _complete.size() : (sep_pos + 1);
}
return;
}
}
- _text = text;
- if (starts_with(text, "LOG VERSION: 2.0")) {
+ _text = &_complete[timestamp_prefix_length];
+ if (textStartsWith("LOG VERSION: 2.0")) {
_logclass = Class::program;
_type = LogEntryType::log_version;
return;
}
- if (starts_with(text, "logging initial states") ||
- starts_with(text, "logging intitial states")) {
+ if (textStartsWith("logging initial states") ||
+ textStartsWith("logging intitial states")) {
_logclass = Class::program;
_type = LogEntryType::log_initial_states;
return;
}
- if (text.find("starting...") != string::npos ||
- text.find("active mode...") != string::npos) {
+ if (textContains("starting...") || textContains("active
mode...")) {
_logclass = Class::program;
_type = LogEntryType::core_starting;
return;
}
- if (text.find("shutting down...") != string::npos ||
- text.find("Bailing out") != string::npos ||
- text.find("standby mode...") != string::npos) {
+ if (textContains("shutting down...") || textContains("Bailing
out") ||
+ textContains("standby mode...")) {
_logclass = Class::program;
_type = LogEntryType::core_stopping;
return;
}
- if (text.find("restarting...") != string::npos) {
+ if (textContains("restarting...")) {
_logclass = Class::program;
_type = LogEntryType::none;
return;
@@ -316,6 +316,14 @@ void LogEntry::classifyLogMessage(const string &text) {
_type = LogEntryType::none;
}
+bool LogEntry::textStartsWith(const string &what) {
+ return _complete.compare(timestamp_prefix_length, what.size(), what) == 0;
+}
+
+bool LogEntry::textContains(const string &what) {
+ return _complete.find(what, timestamp_prefix_length) != string::npos;
+}
+
// The NotifyHelper class has a long, tragic history: Through a long series of
// commits, it suffered from spelling mistakes like "HOST_NOTIFICATION" or
"HOST
// NOTIFICATION" (without a colon), parameter lists not matching the
diff --git a/livestatus/src/LogEntry.h b/livestatus/src/LogEntry.h
index f45f23d..f24267e 100644
--- a/livestatus/src/LogEntry.h
+++ b/livestatus/src/LogEntry.h
@@ -82,7 +82,7 @@ public:
LogEntryType _type;
std::string _complete; // copy of complete unsplit message
const char *_options; // points into _complete after ':'
- std::string _text;
+ const char *_text; // points into _complete or into static data
std::string _host_name;
std::string _svc_desc;
std::string _command_name;
@@ -130,7 +130,9 @@ private:
bool assign(Param par, const std::string &field);
void applyWorkarounds();
- void classifyLogMessage(const std::string &text);
+ void classifyLogMessage();
+ bool textStartsWith(const std::string &what);
+ bool textContains(const std::string &what);
};
#endif // LogEntry_h
diff --git a/livestatus/src/TableLog.cc b/livestatus/src/TableLog.cc
index 1f55496..bf320a3 100644
--- a/livestatus/src/TableLog.cc
+++ b/livestatus/src/TableLog.cc
@@ -71,7 +71,7 @@ TableLog::TableLog(MonitoringCore *mc, LogCache *log_cache)
addColumn(make_unique<OffsetSStringColumn>(
"message", "The complete message line including the
timestamp",
DANGEROUS_OFFSETOF(LogEntry, _complete), -1, -1, -1));
- addColumn(make_unique<OffsetSStringColumn>(
+ addColumn(make_unique<OffsetStringColumn>(
"type",
"The type of the message (text before the colon), the message itself for
info messages",
DANGEROUS_OFFSETOF(LogEntry, _text), -1, -1, -1));