Aserisk 1.6 with FreePbx 2.5 VERY Very slow to reload

I am using asterisk a vm and ivr only no live phones on system, I have 1648 vm box’s now i cannot do a backup and a simple changes takes 11-12 mins just to relaod. any way to help this out or fix.

Thanks

Michael Gravely
8643033945

probably not. We are already aware that when you start to put thousands of voicemail boxes on FreePBX it bogs down to that level as it does a full reload of the dialplan.

If you are doing nothing more than that, you may want to make a vanilla Asterisk install and place the voicemail related configurations into Asterisk realtime.

We’re using freePBX as a backup interface for a DUNDI cluster with around 500 extensions.
Sequential reload on 2 nodes lasted over 5 minutes on carrier-grade servers, after optimizations now it’s around 5 seconds.

That’s about 100 times faster :wink:

So what’s the trick…?

When generating the dialplan freePBX makes several requests to AstDB for each extension.

Request flow goes like this: PHP -> AMI -> AstDB
Each request lasts 0,1 seconds.
Sound small, but multiply that by number of extensions and by 6 foreach loops…

0,1 * 500 * 6 = 300 seconds i.e. 5 minutes.

So to speed things up you just need to eliminate the usage of the AMI interface, so PHP accesses the AstDB directly.

PHP -> AstDB

This can be done easily by overriding the database_get method in the phpagi interface and implementing BerkeleyDB extension for PHP.

Really its a half hour fix…

Hmm,

Could you please file a feature request ticket with your implementation so that the developers could have a look at it?

Sorry if I offend anyone for posting to this (old) thread, but anyone else that might have spent time chasing the solution proposed above may appreciate finding this info here.

We too were finding reload times with Asterisk 1.6 slow and spent a few hours following up on the suggestion that 53rg10 made, trying to get PHP to open the astdb file directly, without any luck. Maybe we’re missing something obvious, but in a stock install of CentOS 5.3 and PHP, I don’t think it’s trivial. If anyone has done this, please share your wisdom.

Out of curiosity (and also because it was so simple to test), we tried replacing the call to the manager interface with an exec to asterisk directly (example: asterisk -rx “database get $family $key”). Applying config changes in FreePBX with about 100 extensions went from 35 seconds to about 12 - almost 3 times faster! Not quite the 100-fold improvement from above, but we’re getting there.

Our next thought was why not just load the entire astdb into memory, once (using asterisk -rx “database show”) and return values from memory in database_get? A FreePBX developer will have to weigh in at some point, but if the astdb is loaded the first time database_get is called (per http request) then we feel that there is very little risk it will not be up-to-date during the entire request (ex: during apply config changes). Not surprisingly, this method was much faster. The same install is now applying config changes in under 1 second! I don’t know if it’s the 100x performance gain reported above, but we’ll take it!

FYI, the database_get function that we’re interested in is the one in the file admin/common/php-asmanager.php

Here is the original function:
[php]
function database_get($family, $key) {
$r = $this->command(“database get “.str_replace(” “,”/”,$family)." “.str_replace(” “,”/",$key));
$data = strpos($r[“data”],“Value:”);
if ($data !== false) {
return trim(substr($r[“data”],6+$data));
} else {
return false;
}
}
[/php]

Here is a version we tested that uses exec calls to Asterisk instead of the Asterisk Manager Interface:

[php]
function database_get($family, $key) {
exec(“asterisk -rx “database get “.str_replace(” “,”/”,$family).” “.str_replace(” “,”/",$key).""",$result);
$data = strpos($result[0],“Value:”);

if ($data !== false) {
	return trim(substr($result[0],6+$data2));
} else {
	return false;
}

}

[/php]

And, finally, here is the code that replaces database_get for the memory caching version we tried:

[php]
var $memAstDB = null;

public function database_get($family, $key) {
if ($this->memAstDB==null){
$this->LoadAstDB();
}

$keyUsed="/".str_replace(" ","/",$family)."/".str_replace(" ","/",$key);

if (array_key_exists($keyUsed,$this->memAstDB)){			
	return $this->memAstDB[$keyUsed];
}
else
	return false;

}

function LoadAstDB(){
if ($this->memAstDB != null) unset($this->memAstDB);
$this->memAstDB = Array();
exec(“asterisk -rx “database show””,$result);
foreach ($result as $row){
$index=strpos($row,":");
if ($index){
$value = trim(substr($row,$index+1));
$key = trim(substr($row,0,$index));
$this->memAstDB[$key]=$value;
}
}
}
[/php]

caching the entire astdb and updating it before finishing is an interesting idea though it does come with potential issues since the database is accessed realtime during call processing and is also updated by other applications such as XML phone scripts, ARI, applications like iSymphony, etc.

This problem persists on freepbx 2.8.x and asterisk 1.6.x

with this patch, my ‘apply configuration’ for 250 extensions came from 1.5 minute to 10 seconds…

Amazing!!!

Is there a way to put this as a stable code instead of a patch?

I think that a 5 minute ‘apply configuration’ is a ‘potential/annoying issue’ bigger then a cache apply that get seconds to run…

filing a ticket to the tracker with a patch of the changes would be a start to having it looked at more closely.

I would also suggest enhancing it by adding optional additional parameters to the modified function calls that would allow them to run in their current mode unless specified to use caching.

Lastly, I would also ask you or others who are having this issue what else you might be running on your systems that may be access the manager. It would be useful to know if the gross issues are because of an overloaded manager vs. or something like that? (not that caching would further help things but …)

One more thing, it would be very valuable to know if using:

database_show()

vs.

exec("asterisk -rx \"database show\"",$result);

makes any significant difference as it is much preferable to keep running through manager.

and yet one more thing, it would be very useful to modify database_put and database_del and database_deltree such that IF there is a buffered version present, that it also updates the buffered version to make sure that subsequent calls are accurately reflected…

See #4435

Continued suggestions/feedback related to the speedups of caching should be provided on the ticket. Thanks for the suggestion.