Cache locals of script frame used for assign where eval

to avoid malloc(). This BREAKS assign where locals.x = 1.
This commit is contained in:
Alexander A. Klimov 2022-11-08 16:12:42 +01:00
parent b6f8f36b3a
commit 141ef98499
10 changed files with 98 additions and 43 deletions

View File

@ -320,3 +320,13 @@ void Checkable::CleanDeadlinedExecutions(const Timer * const&)
} }
} }
} }
Dictionary::Ptr Checkable::GetFrozenLocalsForApply()
{
if (!m_FrozenLocalsForApply) {
m_FrozenLocalsForApply = MakeLocalsForApply();
m_FrozenLocalsForApply->Freeze();
}
return m_FrozenLocalsForApply;
}

View File

@ -207,12 +207,18 @@ public:
static Object::Ptr GetPrototype(); static Object::Ptr GetPrototype();
Dictionary::Ptr GetFrozenLocalsForApply();
protected: protected:
void Start(bool runtimeCreated) override; void Start(bool runtimeCreated) override;
void OnConfigLoaded() override; void OnConfigLoaded() override;
void OnAllConfigLoaded() override; void OnAllConfigLoaded() override;
virtual Dictionary::Ptr MakeLocalsForApply() = 0;
private: private:
Dictionary::Ptr m_FrozenLocalsForApply;
mutable std::mutex m_CheckableMutex; mutable std::mutex m_CheckableMutex;
bool m_CheckRunning{false}; bool m_CheckRunning{false};
long m_SchedulingOffset; long m_SchedulingOffset;

View File

@ -70,16 +70,20 @@ bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyR
msgbuf << "Evaluating 'apply' rule (" << di << ")"; msgbuf << "Evaluating 'apply' rule (" << di << ")";
CONTEXT(msgbuf.str()); CONTEXT(msgbuf.str());
Host::Ptr host; ScriptFrame frame (false);
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
ScriptFrame frame(true); if (rule.GetScope() || rule.GetFTerm()) {
if (rule.GetScope()) frame.Locals = new Dictionary();
rule.GetScope()->CopyTo(frame.Locals);
frame.Locals->Set("host", host); if (rule.GetScope()) {
if (service) rule.GetScope()->CopyTo(frame.Locals);
frame.Locals->Set("service", service); }
checkable->GetFrozenLocalsForApply()->CopyTo(frame.Locals);
frame.Locals->Freeze();
} else {
frame.Locals = checkable->GetFrozenLocalsForApply();
}
bool match = false; bool match = false;
@ -103,7 +107,7 @@ bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyR
for (const Value& instance : arr) { for (const Value& instance : arr) {
String name = rule.GetName(); String name = rule.GetName();
frame.Locals->Set(rule.GetFKVar(), instance); frame.Locals->Set(rule.GetFKVar(), instance, true);
name += instance; name += instance;
if (EvaluateApplyRuleInstance(checkable, name, frame, rule, skipFilter)) if (EvaluateApplyRuleInstance(checkable, name, frame, rule, skipFilter))
@ -117,8 +121,8 @@ bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyR
ObjectLock olock (dict); ObjectLock olock (dict);
for (auto& kv : dict) { for (auto& kv : dict) {
frame.Locals->Set(rule.GetFKVar(), kv.first); frame.Locals->Set(rule.GetFKVar(), kv.first, true);
frame.Locals->Set(rule.GetFVVar(), kv.second); frame.Locals->Set(rule.GetFVVar(), kv.second, true);
if (EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, frame, rule, skipFilter)) if (EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, frame, rule, skipFilter))
match = true; match = true;

View File

@ -328,3 +328,8 @@ bool Host::ResolveMacro(const String& macro, const CheckResult::Ptr&, Value *res
return false; return false;
} }
Dictionary::Ptr Host::MakeLocalsForApply()
{
return new Dictionary({{ "host", this }});
}

View File

@ -57,6 +57,8 @@ protected:
void CreateChildObjects(const Type::Ptr& childType) override; void CreateChildObjects(const Type::Ptr& childType) override;
Dictionary::Ptr MakeLocalsForApply() override;
private: private:
mutable std::mutex m_ServicesMutex; mutable std::mutex m_ServicesMutex;
std::map<String, intrusive_ptr<Service> > m_Services; std::map<String, intrusive_ptr<Service> > m_Services;

View File

@ -69,16 +69,20 @@ bool Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const Appl
msgbuf << "Evaluating 'apply' rule (" << di << ")"; msgbuf << "Evaluating 'apply' rule (" << di << ")";
CONTEXT(msgbuf.str()); CONTEXT(msgbuf.str());
Host::Ptr host; ScriptFrame frame (false);
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
ScriptFrame frame(true); if (rule.GetScope() || rule.GetFTerm()) {
if (rule.GetScope()) frame.Locals = new Dictionary();
rule.GetScope()->CopyTo(frame.Locals);
frame.Locals->Set("host", host); if (rule.GetScope()) {
if (service) rule.GetScope()->CopyTo(frame.Locals);
frame.Locals->Set("service", service); }
checkable->GetFrozenLocalsForApply()->CopyTo(frame.Locals);
frame.Locals->Freeze();
} else {
frame.Locals = checkable->GetFrozenLocalsForApply();
}
bool match = false; bool match = false;
@ -102,7 +106,7 @@ bool Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const Appl
for (const Value& instance : arr) { for (const Value& instance : arr) {
String name = rule.GetName(); String name = rule.GetName();
frame.Locals->Set(rule.GetFKVar(), instance); frame.Locals->Set(rule.GetFKVar(), instance, true);
name += instance; name += instance;
if (EvaluateApplyRuleInstance(checkable, name, frame, rule, skipFilter)) if (EvaluateApplyRuleInstance(checkable, name, frame, rule, skipFilter))
@ -116,8 +120,8 @@ bool Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const Appl
ObjectLock olock (dict); ObjectLock olock (dict);
for (auto& kv : dict) { for (auto& kv : dict) {
frame.Locals->Set(rule.GetFKVar(), kv.first); frame.Locals->Set(rule.GetFKVar(), kv.first, true);
frame.Locals->Set(rule.GetFVVar(), kv.second); frame.Locals->Set(rule.GetFVVar(), kv.second, true);
if (EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, frame, rule, skipFilter)) if (EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, frame, rule, skipFilter))
match = true; match = true;

View File

@ -68,16 +68,20 @@ bool ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const
msgbuf << "Evaluating 'apply' rule (" << di << ")"; msgbuf << "Evaluating 'apply' rule (" << di << ")";
CONTEXT(msgbuf.str()); CONTEXT(msgbuf.str());
Host::Ptr host; ScriptFrame frame (false);
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
ScriptFrame frame(true); if (rule.GetScope() || rule.GetFTerm()) {
if (rule.GetScope()) frame.Locals = new Dictionary();
rule.GetScope()->CopyTo(frame.Locals);
frame.Locals->Set("host", host); if (rule.GetScope()) {
if (service) rule.GetScope()->CopyTo(frame.Locals);
frame.Locals->Set("service", service); }
checkable->GetFrozenLocalsForApply()->CopyTo(frame.Locals);
frame.Locals->Freeze();
} else {
frame.Locals = checkable->GetFrozenLocalsForApply();
}
bool match = false; bool match = false;
@ -101,7 +105,7 @@ bool ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const
for (const Value& instance : arr) { for (const Value& instance : arr) {
String name = rule.GetName(); String name = rule.GetName();
frame.Locals->Set(rule.GetFKVar(), instance); frame.Locals->Set(rule.GetFKVar(), instance, true);
name += instance; name += instance;
if (EvaluateApplyRuleInstance(checkable, name, frame, rule, skipFilter)) if (EvaluateApplyRuleInstance(checkable, name, frame, rule, skipFilter))
@ -115,8 +119,8 @@ bool ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const
ObjectLock olock (dict); ObjectLock olock (dict);
for (auto& kv : dict) { for (auto& kv : dict) {
frame.Locals->Set(rule.GetFKVar(), kv.first); frame.Locals->Set(rule.GetFKVar(), kv.first, true);
frame.Locals->Set(rule.GetFVVar(), kv.second); frame.Locals->Set(rule.GetFVVar(), kv.second, true);
if (EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, frame, rule, skipFilter)) if (EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, frame, rule, skipFilter))
match = true; match = true;

View File

@ -63,10 +63,20 @@ bool Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule, bo
msgbuf << "Evaluating 'apply' rule (" << di << ")"; msgbuf << "Evaluating 'apply' rule (" << di << ")";
CONTEXT(msgbuf.str()); CONTEXT(msgbuf.str());
ScriptFrame frame(true); ScriptFrame frame (false);
if (rule.GetScope())
rule.GetScope()->CopyTo(frame.Locals); if (rule.GetScope() || rule.GetFTerm()) {
frame.Locals->Set("host", host); frame.Locals = new Dictionary();
if (rule.GetScope()) {
rule.GetScope()->CopyTo(frame.Locals);
}
host->GetFrozenLocalsForApply()->CopyTo(frame.Locals);
frame.Locals->Freeze();
} else {
frame.Locals = host->GetFrozenLocalsForApply();
}
bool match = false; bool match = false;
@ -91,7 +101,7 @@ bool Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule, bo
String name = rule.GetName(); String name = rule.GetName();
if (!rule.GetFKVar().IsEmpty()) { if (!rule.GetFKVar().IsEmpty()) {
frame.Locals->Set(rule.GetFKVar(), instance); frame.Locals->Set(rule.GetFKVar(), instance, true);
name += instance; name += instance;
} }
@ -106,8 +116,8 @@ bool Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule, bo
ObjectLock olock (dict); ObjectLock olock (dict);
for (auto& kv : dict) { for (auto& kv : dict) {
frame.Locals->Set(rule.GetFKVar(), kv.first); frame.Locals->Set(rule.GetFKVar(), kv.first, true);
frame.Locals->Set(rule.GetFVVar(), kv.second); frame.Locals->Set(rule.GetFVVar(), kv.second, true);
if (EvaluateApplyRuleInstance(host, rule.GetName() + kv.first, frame, rule, skipFilter)) if (EvaluateApplyRuleInstance(host, rule.GetName() + kv.first, frame, rule, skipFilter))
match = true; match = true;

View File

@ -285,3 +285,11 @@ std::pair<Host::Ptr, Service::Ptr> icinga::GetHostService(const Checkable::Ptr&
else else
return std::make_pair(static_pointer_cast<Host>(checkable), nullptr); return std::make_pair(static_pointer_cast<Host>(checkable), nullptr);
} }
Dictionary::Ptr Service::MakeLocalsForApply()
{
return new Dictionary({
{ "host", m_Host },
{ "service", this }
});
}

View File

@ -51,6 +51,8 @@ public:
protected: protected:
void CreateChildObjects(const Type::Ptr& childType) override; void CreateChildObjects(const Type::Ptr& childType) override;
Dictionary::Ptr MakeLocalsForApply() override;
private: private:
Host::Ptr m_Host; Host::Ptr m_Host;