EEConf 2024 is around the corner! EEConf 2024
So I have a very large _global_vars array (3205 items). Probably too large, but it is what it is and I can’t change it. I’m getting a “regular expression is too large” error b/c the $regex value in this loop is a very, very long string.
$regex = $this->getGlobalsRegex();
while (preg_match_all($regex, $this->template, $result))
I did some testing with a smaller _global_vars array (~600 items) by changing that loop to just do a strpos() on the template before swaping the variable contents. In my tests it took approximately 0.014 seconds to loop over the _global_vars array. The preg_match_all by comparison took approximately 0.005 seconds. Its about a 64% difference in speed, but still a very small fraction of time. Since preg_match_all has a limitation depending on the compiled php settings would it make sense to change it to a loop with a strpos check?
preg_match_all
pro: faster
con: puts a limit on the number of _global_vars you can have
foreach & strpos
pro: no limit on the _global_vars
con: slower
Yes we specifically moved to regex for the performance boost, but that assumed global vars would be used reasonably. We’d need to look into ways to accommodate this without reverting back to the poor performance. But before we sink time into this and thus take time away from important work, is there a legitimate use case for this many global variables?
In our case we have a Structure/Pages array of over 3000 pages, which are all created as early parsed global variables by Publisher. So I guess technically this is a Publisher issue, but it used to not be an issue. This is partially an architecture problem on our site b/c its putting dang near everything in Structure when it shouldn’t need to. That was before my time and now I’m having to deal with it. I can hack the core to change that loop back to the old version, but thats less than ideal.
Ok, I may have something. Replace your Template.php with this and see how it works:
The getGlobalsRegex function seems to change the behavior/usage of _global_vars when used in a layout file when items are added to the array from the template_fetch_template hook.
From Slack:
I’m using the In:sert extension in EE3. It works great for any template/global_var that isn’t used in my layout file. E.g. {in:sert:embeds/_footer-top-en} works fine everywhere except the layout file. In:sert is using the template_fetch_template hook and its correctly adding an item to the _global_vars array, but by the time the layout file gets parsed, the items are not in the _global_vars array… its using an old _global_vars array or something.
Making this change returns it to its expected behavior:
private function getGlobalsRegex()
{
//if ( ! isset($this->globals_regex))
//{
$global_names = array_keys(ee()->config->_global_vars);
$global_names = array_map(
function($str)
{
return preg_quote($str, '/');
},
$global_names
);
$global_names = $this->chunkGlobalsArray($global_names);
$this->globals_regex = array_map(
function($array)
{
return '/'.LD.'('.implode('|', $array).')'.RD.'/';
},
$global_names
);
//}
return $this->globals_regex;
}
Ok I’ve put some caching in place based on what’s in the globals array. See how this works, if you want:
To test that I’d actually have to roll back a few changes. I assume the only thing you really changed was adding the cache check in getGlobalsRegex?
$global_names = array_keys(ee()->config->_global_vars); $cache_key = md5(serialize($global_names));
I figured that would probably work, just wondering how much processing time it adds to serialize and md5 a large global vars array.
Packet Tide owns and develops ExpressionEngine. © Packet Tide, All Rights Reserved.