retrieve_conf as a function

Hi,

I am working on porting FreePBX to and embedded IP-PBX which has only a small amount of memory and runs uClinux (no MMU). When “Apply Configuration Changes” is clicked retrieve_conf gets called via exec from the main php-cgi process. On my system this uses too much memory.

I was wondering if there is any reason why retrieve_conf could not be called as a function, rather than via exec? I guess a exec-able version would still be reqd for the module install process.

Thanks,

David

Before you get too far, I talked with Xorcom some time ago who tried to get FreePBX running on their blackfin based appliance with no MMU, and they found that it didn’t work because of the memory fragmentation that quickly happens with dialparties.agi and other AGI scripts that are constantly run as part of the dialplan - so if you are running into problems with retrieve_conf, I wonder what else you have in store once you get past that…

Yes, several people from the Blackfin community have reported similar problems with fragmentation while running PHP. Not having an MMU certainly is a challenge. We are working through this issue on the Blackfin Asterisk Forum:

http://blackfin.uclinux.org/gf/project/asterisk/forum/?action=ForumBrowse&_forum_action=MessageReply&message_id=52146

Thanks for tip on those AGIs Philippe. So I guess the requirement is that we need to be able to exec PHP scripts at any time on the Blackfin, so a hack to retrieve_conf is not the right way to go. I might take a look in that direction, and run some long term tests on calling those AGIs.

BTW the patches I mentioned in my post to the sqlite3 thread are for the x86, so I hope they are useful for the x86 regardless of the outcome of the Blackfin work.

Cheers,

David

Hi,

To test FreePBX PHP AGIs like dialparties.agi on the Blackfin IP04 I set up this test:

extensions_custom.conf:

[from-internal-custom]

exten => 1234,1,Answer
exten => 1234,2,NoOp(About to call dial x)
exten => 1234,3,Macro(dial,1,’’,1235)
exten => 1234,4,NoOp(After calling dial)

exten => 1235,1,Answer
exten => 1235,2,Wait(10)
exten => 1235,3,Hangup

iax.conf:

[guest]
type=user
context=from-internal-custom
callerid=“Guest IAX User”

Then I wrote an expect script to login to the Blackfin target (an IP04 with * 1.4.4) and execute this line many times at the * CLI:

CLI> originate IAX2/guest@localhost/1235 extension 1234@from-internal-custom

which makes a call between 1234 & 1235, executing dialplan.agi for each call. I have now made around 10,000 calls on the Blackfin target with no serious memory problems. Thats a lot of calls for our typical 4 port PBX.

I did notice that after a few 1000 calls Asterisk’s memory consumption had increased by approx 1 MB, not sure why. Could be some tables/logs that are growing, or maybe CDR etc.

I think the problem the Xorcom guys may have been having is not so much fragmentation as file buffering. You see by default uClinux on the Blackfin can use up to 100% of its memory to buffer files. However you can throttle this with something like:

echo 10 > /proc/sys/vm/pagecache_ratio

which sets asaide a maximum of 10% of system memory for file buffers. If you leave this at the default 100% after many files are accessed the system memory can be consumed to a point where large apps like PHP can’t load.

Anyway - looks like a good result for running AGIs. Its still sucks that PHP uses up to 9M each time it runs - uClinux is inefficient in it’s memory usage and we dont have much memory (just 64M) compared to a x86. So time to look at retrieve_conf again…

Thanks,

David

What is the build of PHP you are using? By minimizing the number of php extensions (eg, removing all unneeded extensions), you should be able to minimize the amount of RAM it uses.

Possibly the other alternative is FastAGI - though for that you’d need a FastAGI server. However, if written properly, there would just be one instance of PHP itself loaded (the fastagi server), and each script invoked would just use enough memory to load the script and store any data in variables (+overhead).

It’s nice to see people working on this sort of thing though, and I’m glad you’re making progress.

Hi Greg,

Thanks for your comments and encouragement :slight_smile:

We are using PHP 5.2.5, here are the ./configure options and flags we use:
PHP_CONFIGURE_OPTS=–host=bfin-linux-uclibc --target=bfin-linux-uclibc --disable-all --disable-ipv6 --enable-session --with-sqlite --with-pcre-regex --with-pear=$(PHP_DIR)/pear --enable-pdo --with-pdo-sqlite --with-sqlite3=$(DL_DIR)/ext/pdo_sqlite/sqlite/src --enable-fastcgi --enable-xml --enable-libxml --with-libxml-dir=$(STAGING_DIR) --enable-memory-limit --prefix=/etc --with-config-file-path=/etc --with-gettext

export CFLAGS = -Os -g -Wall -I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/include/libxml2
export LDFLAGS = -L$(STAGING_DIR)/usr/lib -lpthread -ldl -lintl

For some strange reason we need Pear enabled - otherwise sqlite3 calls from PHP hang or generate core dumps. The actual php binary is only about 2.4M, so somehow the extra memory is getting chewed at run time. I am not sure if this is due to loading the various .so’s (libxml, libsqlite3 etc), or run time memory requirements of PHP.

We actually used fast-cgi for the webserver to php-cgi connection. Thanks for your suggestion on fastAGI - that would help speed up dialling.

Cheers,

David

Hi,

I did a little more research (e.g. PHP zend_alloc.c, README.ZEND_MM) to work out where all the memory was being used on our little uClinux system. Best as I can tell, PHP really does need all the memory that is being allocated, no real inefficiencies with the Zend memory manager. Lot of code to load up and compiel I guess.

However I wouldn’t be surprised if the uClinux MM is a little inefficient - PHP reports 5.1M peak memory used however I can see the free memory on the Blackfin drop by around 15M when I run retrieve_conf from the command line. Or maybe I don’t understand how the PHP peak memory func works.

So with the current FreePBX design, when we click “Apply Configuration Changes” we have php-cgi exec-ing php. Both use a peak of around 30M so thats 30M spare memory we need on our 64M system. Not pretty.

So I messed around with retrieve_conf and the do_update() function in admin/functions.inc.php to create a couple of include files that are included from the config.php switch statement:

	case 'reload':
		/** AJAX handler for reload event
		 */
		include_once('common/json.inc.php');
		// DR: include as global code
		include_once('do_reload.php');
		//$response = do_reload();
		$json = new Services_JSON();
		echo $json->encode($response);

It was a bit tricky as retrieve_conf expects a bunch of stuff to be globals. Anyway with this mod I can (finally) click on “Apply Config Changes”! Yayyyyyy… I have managed to set up a couple of extensions/routes/trunks and make a few calls on my IP04. While running the retreive_conf code memory usage is no higher than the regular cgi code, ie 15M total. So thats 15M saved - pretty significant.

A nice step forward. Next step is to make sure those dialling AGIs can run at the same time, might be in for some probs their although the amount of PHP they have to load look smaller than for the web interface.

Also I am not sure how to handle patching retrieve_conf/config.php etc so that this mod is portable and easy to maintain. Any ideas?

Pretty amazing to see this running on an open hardware embedded IP-PBX that consumes just 3W:

http://www.rowetel.com/ucasterisk/ip04.html

Cheers,

David