I just had a case in where it was nearly impossible to open the rules UI.
First I tried to profile the script execution, since there were no watchdog or php error log entries.
This idea failed miserably because in no time the profile file grew to over 2.5 GB.
I remove all rules but one, still the same issue (maybe it was related to the complexity of the component).
Now I decided to cancel the execution and parse the unfinished profiling file.
The result was interessting:
> 40'000 calls of RulesPlugin::availableVariables() (see attached image)
Wow.
If I understand the concept correctly, every time this function is called, it bubbles the call up till it reaches the root.
In my case I had a lot of conditions and actions in one component - every evaluation of an data:select setting (and I think also on other occasions) the event bubbled up the whole tree, leading to doing the same evaluation over and over and over and over... again.
Then I changed to code according to this:
From:
/**
* Returns info about variables available to be used as arguments for this
* element.
*/
public function availableVariables() {
return !$this->isRoot() ? $this->parent->stateVariables($this) : RulesState::defaultVariables();
}
To:
/**
* Returns info about variables available to be used as arguments for this
* element.
*/
public function availableVariables() {
if (isset($this->availableVariables)) {
return $this->availableVariables;
}
$this->availableVariables = !$this->isRoot() ? $this->parent->stateVariables($this) : RulesState::defaultVariables();
return $this->availableVariables;
}
This approach stores the results of the evaluation and once a child asks for the available variables it isn't necessary to bubble up the whole tree again.
Result in my case is that the ui now loads in no time instead not at all.
To be honest I'm not sure that there aren't bad sideeffects but for me it looks like every thing is still working ;)
If the approach is confirmed I'll happily provide a patch :)
| Comment | File | Size | Author |
|---|---|---|---|
| #1 | rules_available_variables.patch | 7 KB | fago |
| RulesPlugin_availableVariables.png | 134.9 KB | das-peter |
Comments
Comment #1
fagoindeed, that results in a lot of repetitive calls and calculations, so a static cache would make sense to me. Attached patch implements one, could you test the performance impact in your setup? I'd be also interested whether memory consumption goes up with the patch?
Unrelated, it would be probably a nice performance improvement to cache info alterations via info_alter for actions, so availableVariables() shouldn't be necessary at run-time at all.
Comment #2
fagoComment #3
fagoComment #4
das-peter commentedThanks fago!
I've applied the patch. Performance wise it's still the same as before:
Without the patch I'm unable to open the components page. If I apply the patch the page opens fairly quick.
I've also smoke tested it a bit on our system and it seems to work well.
Comment #5
fagook, tested the patch on a site with ~50 reaction rules (making use of various components).
The page load time of the reaction rules overview decreased from ~1200ms to ~590ms with the page, whereas peak memory usage went up from 41 to 41,7MB. I guess that's very well worth it -> committed.