From fd5d6de52e758e6c6387b3e05cd11b27ec33232c Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Thu, 22 Oct 2015 08:28:40 +0200 Subject: [PATCH] Improve performance for Livestatus queries refs #10428 --- lib/icinga/host.cpp | 7 +-- lib/icinga/host.hpp | 2 +- lib/livestatus/hoststable.cpp | 21 ++++++--- lib/livestatus/livestatusquery.cpp | 73 ++++++++++++++++++------------ lib/livestatus/livestatusquery.hpp | 4 +- 5 files changed, 67 insertions(+), 40 deletions(-) diff --git a/lib/icinga/host.cpp b/lib/icinga/host.cpp index 955bba397..8b7dd25a0 100644 --- a/lib/icinga/host.cpp +++ b/lib/icinga/host.cpp @@ -91,14 +91,15 @@ void Host::Stop(void) // TODO: unregister slave services/notifications? } -std::set Host::GetServices(void) const +std::vector Host::GetServices(void) const { boost::mutex::scoped_lock lock(m_ServicesMutex); - std::set services; + std::vector services; + services.reserve(m_Services.size()); typedef std::pair ServicePair; BOOST_FOREACH(const ServicePair& kv, m_Services) { - services.insert(kv.second); + services.push_back(kv.second); } return services; diff --git a/lib/icinga/host.hpp b/lib/icinga/host.hpp index 1759a4cf7..8f64a52c7 100644 --- a/lib/icinga/host.hpp +++ b/lib/icinga/host.hpp @@ -43,7 +43,7 @@ public: intrusive_ptr GetServiceByShortName(const Value& name); - std::set > GetServices(void) const; + std::vector > GetServices(void) const; void AddService(const intrusive_ptr& service); void RemoveService(const intrusive_ptr& service); diff --git a/lib/livestatus/hoststable.cpp b/lib/livestatus/hoststable.cpp index cd16f7906..f1b223640 100644 --- a/lib/livestatus/hoststable.cpp +++ b/lib/livestatus/hoststable.cpp @@ -1478,9 +1478,12 @@ Value HostsTable::ServicesAccessor(const Value& row) if (!host) return Empty; - Array::Ptr services = new Array(); + std::vector rservices = host->GetServices(); - BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) { + Array::Ptr services = new Array(); + services->Reserve(rservices.size()); + + BOOST_FOREACH(const Service::Ptr& service, rservices) { services->Add(service->GetShortName()); } @@ -1494,9 +1497,12 @@ Value HostsTable::ServicesWithStateAccessor(const Value& row) if (!host) return Empty; - Array::Ptr services = new Array(); + std::vector rservices = host->GetServices(); - BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) { + Array::Ptr services = new Array(); + services->Reserve(rservices.size()); + + BOOST_FOREACH(const Service::Ptr& service, rservices) { Array::Ptr svc_add = new Array(); svc_add->Add(service->GetShortName()); @@ -1515,9 +1521,12 @@ Value HostsTable::ServicesWithInfoAccessor(const Value& row) if (!host) return Empty; - Array::Ptr services = new Array(); + std::vector rservices = host->GetServices(); - BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) { + Array::Ptr services = new Array(); + services->Reserve(rservices.size()); + + BOOST_FOREACH(const Service::Ptr& service, rservices) { Array::Ptr svc_add = new Array(); svc_add->Add(service->GetShortName()); diff --git a/lib/livestatus/livestatusquery.cpp b/lib/livestatus/livestatusquery.cpp index ef2affd44..c216da6bc 100644 --- a/lib/livestatus/livestatusquery.cpp +++ b/lib/livestatus/livestatusquery.cpp @@ -403,34 +403,50 @@ Filter::Ptr LivestatusQuery::ParseFilter(const String& params, unsigned long& fr return filter; } -void LivestatusQuery::PrintResultSet(std::ostream& fp, const Array::Ptr& rs) const +void LivestatusQuery::BeginResultSet(std::ostream& fp) const +{ + if (m_OutputFormat == "json" || m_OutputFormat == "python") + fp << "["; +} + +void LivestatusQuery::EndResultSet(std::ostream& fp) const +{ + if (m_OutputFormat == "json" || m_OutputFormat == "python") + fp << "]"; +} + +void LivestatusQuery::AppendResultRow(std::ostream& fp, const Array::Ptr& row, bool& first_row) const { if (m_OutputFormat == "csv") { - ObjectLock olock(rs); + bool first = true; - BOOST_FOREACH(const Array::Ptr& row, rs) { - bool first = true; + ObjectLock rlock(row); + BOOST_FOREACH(const Value& value, row) { + if (first) + first = false; + else + fp << m_Separators[1]; - ObjectLock rlock(row); - BOOST_FOREACH(const Value& value, row) { - if (first) - first = false; - else - fp << m_Separators[1]; - - if (value.IsObjectType()) - PrintCsvArray(fp, value, 0); - else - fp << value; - } - - fp << m_Separators[0]; + if (value.IsObjectType()) + PrintCsvArray(fp, value, 0); + else + fp << value; } + + fp << m_Separators[0]; } else if (m_OutputFormat == "json") { - fp << JsonEncode(rs); + if (!first_row) + fp << ", "; + + fp << JsonEncode(row); } else if (m_OutputFormat == "python") { - PrintPythonArray(fp, rs); + if (!first_row) + fp << ", "; + + PrintPythonArray(fp, row); } + + first_row = false; } void LivestatusQuery::PrintCsvArray(std::ostream& fp, const Array::Ptr& array, int level) const @@ -503,7 +519,9 @@ void LivestatusQuery::ExecuteGetHelper(const Stream::Ptr& stream) else columns = table->GetColumnNames(); - Array::Ptr rs = new Array(); + std::ostringstream result; + bool first_row = true; + BeginResultSet(result); if (m_Aggregators.empty()) { Array::Ptr header = new Array(); @@ -516,8 +534,6 @@ void LivestatusQuery::ExecuteGetHelper(const Stream::Ptr& stream) BOOST_FOREACH(const String& columnName, columns) column_objs.push_back(std::make_pair(columnName, table->GetColumn(columnName))); - rs->Reserve(1 + objects.size()); - BOOST_FOREACH(const LivestatusRowValue& object, objects) { Array::Ptr row = new Array(); @@ -531,11 +547,11 @@ void LivestatusQuery::ExecuteGetHelper(const Stream::Ptr& stream) } if (m_ColumnHeaders) { - rs->Add(header); + AppendResultRow(result, header, first_row); m_ColumnHeaders = false; } - rs->Add(row); + AppendResultRow(result, row, first_row); } } else { std::vector stats(m_Aggregators.size(), 0); @@ -563,7 +579,7 @@ void LivestatusQuery::ExecuteGetHelper(const Stream::Ptr& stream) header->Add("stats_" + Convert::ToString(i)); } - rs->Add(header); + AppendResultRow(result, header, first_row); } Array::Ptr row = new Array(); @@ -587,11 +603,10 @@ void LivestatusQuery::ExecuteGetHelper(const Stream::Ptr& stream) for (size_t i = 0; i < m_Aggregators.size(); i++) row->Add(stats[i]); - rs->Add(row); + AppendResultRow(result, row, first_row); } - std::ostringstream result; - PrintResultSet(result, rs); + EndResultSet(result); SendResponse(stream, LivestatusErrorOK, result.str()); } diff --git a/lib/livestatus/livestatusquery.hpp b/lib/livestatus/livestatusquery.hpp index 9b5c4ad09..822bde239 100644 --- a/lib/livestatus/livestatusquery.hpp +++ b/lib/livestatus/livestatusquery.hpp @@ -97,7 +97,9 @@ private: unsigned long m_LogTimeUntil; String m_CompatLogPath; - void PrintResultSet(std::ostream& fp, const Array::Ptr& rs) const; + void BeginResultSet(std::ostream& fp) const; + void EndResultSet(std::ostream& fp) const; + void AppendResultRow(std::ostream& fp, const Array::Ptr& row, bool& first_row) const; void PrintCsvArray(std::ostream& fp, const Array::Ptr& array, int level) const; void PrintPythonArray(std::ostream& fp, const Array::Ptr& array) const; static String QuoteStringPython(const String& str);