Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > 78f79c2dbfda63e3334e2c4c04c85c29 > files > 7

php-mcache-1.2.0-0.beta10.18mdv2010.0.i586.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>mcache PHP Extension</title>
</head>
<body>

<h1>mcache PHP Extension</h1>

<h2>Contents</h2>
<ul>
<li><a href="./#intro">Introduction</a></li>
<li><a href="./#download">Download</a></li>
<li><a href="./#errata">Errata</a></li>
<li><a href="./#install">Installation</a></li>
<li><a href="./#usage">Example Usage</a></li>
<li><a href="./#performance">Performance</a></li>
<li><a href="./#license">Licensing</a></li>
</ul>

<a name="intro" />
<h2>Introduction</h2>

<p>
<a href=".">mcache</a> is a <a href="http://www.php.net">PHP</a> extension that aims to enable developers to easily and efficiently cache data to <a href="http://www.danga.com/memcached/">Memcached</a> servers.  <a href="http://www.danga.com/memcached/">Memcached</a> is a distributed data caching system developed by <a href="http://www.danga.com">Danga</a> which aims to reduce load on central bottlenecks like RDBMS's.  The mcache php extension has been developed by <a href="mailto:johnm@klir.com">John McCaskey</a> and is a wrapper around <a href="http://people.freebsd.org/~seanc/libmemcache/">libmemcache</a>.  Both Sean Chittenden (author of libmemcache), and Antony Dovgal (author of the original PECL memcached extensions) deserve some of the credit for this work.  Without the excellent C API of libmemcache I would have never written this extension, and likewise without the example of the PECL extension provided by Antony I would likely have taken much longer to learn how to write a PHP extension properly.
</p>

<p>
The primary advantage to using this mcache extension over other PHP extensions is speed, and functionality.  Previously several PHP memcache API's have existed.  Several of these are very good feature-wise, but very slow due to native PHP implementation.  The PECL extension has excellent speed (although not as good as mcache), but does not support multiple servers.  Users have been forced to choose between speed and functionality.  With the introduction of this new extension that is no longer the case.  Furthermore, because this extension is based off <a href="http://people.freebsd.org/~seanc/libmemcache/">libmemcache</a> it will easily benefit from any testing, bug fixes, or enhancements made to the underlying library.
</p>

<a name="download" />
<h2>Download</h2>

<h4><a href="./php-mcache-ext-1.2.0-beta10.tar.gz">mcache extension 1.2.0 beta10</a></h3>
<p>Changes</p>
<ul>
<li><strong>SEGFAULT when getting long values which were not serialized</strong>/li>
<li><strong>Fix for compilation with ZTS enabled for PHP. -- Thanks Elan Ruusamäe!</strong></li>
<li><strong>This build is compatible with libmemcache 1.4.0b9, and is not guranteed to work with older or newer builds!!</strong></li>
</ul>

<h4><a href="./php-mcache-ext-1.2.0-beta9.tar.gz">mcache extension 1.2.0 beta9</a></h3>
<p>Changes</p>
<ul>
<li><strong>SEGFAULT due to error handling, and changes in memory context handling in recent libmemcache betas.  This build is compatible with libmemcache 1.4.0b9, and is not guranteed to work with older or newer builds!!</strong></li>
</ul>

<h4><a href="./php-mcache-ext-1.2.0-beta8.tar.gz">mcache extension 1.2.0 beta8</a></h3>
<p>Changes</p>
<ul>
<li><strong>SEGFUALT in error handling fixed</strong>That's right, there was another error fault remaining.  Fixing it however would trigger some bugs in older libmemcache builds so I hadn't done it yet.  The latest beta of libmemcache (1.4.0b4 as of this writing) fixes these issues and this build should finally be fairly stable.</li>
</ul>

<h3><a href="./php-mcache-ext-1.2.0-beta7.tar.gz">mcache extension 1.2.0 beta7</a></h3>
<p>Changes</p>
<ul>
<li><strong>SEGFAULT in error handling fixed</strong>Previous betas didn't handle initializing the error context correctly.  This is fixed.</li>
</ul>

<h3><a href="./php-mcache-ext-1.2.0-beta6.tar.gz">mcache extension 1.2.0 beta6</a></h3>
<p>Changes</p>
<ul>
<li><strong>Incr/Decr/Get/Stats calls return NULL on failure</strong> -- Several people have been clamoring for this change.  This is benificial in that it makes the API closer to the commonly used PECL client so people converting to php-mcache have an easier time.  It also seems to make sense for get() as more people want to store a FALSE than a NULL in the cache.</li>
<li><strong>Compilation/Installation modified to work more smoothly with newer libmemcache builds</strong> -- php-mcache no longer sucks in all the libmemcache source directly.  It now links against the libmemcache library directly.  <strong>Please see the updated installation instructions below!</strong></li>
</ul>

<h3><a href="./php-mcache-ext-1.2.0-beta5.tar.gz">mcache extension 1.2.0 beta5</a></h3>
<p>Changes</p>
<ul>
<li><strong>Incr/Decr calls return FALSE on failure</strong> -- This was requested by several people and makes more sense than returning 0 as it does presently.  If you are using incr/decr and detecting failures by checking for 0 you may need to update your code of course PHP considers 0 == FALSE so unless you are using === then your code will likely continue working without modification.</li>
</ul>

<h3><a href="./php-mcache-ext-1.2.0-beta4.tar.gz">mcache extension 1.2.0 beta4</a></h3>
<p>Changes</p>
<ul>
<li><strong>Support for libmemcache 1.3.x beta builds (1.3.x is now required infact...)</strong></li>
<li><strong>Fixed to compile on older non C99 compliant compilers</strong> --  Some variables were not declared at the top of blocks as required in older C specs.  Thanks to Jacob Coby off the memcached list for pointing this out as the cause of several others compilation issues.</li>
<li><strong>Improved error handling</strong> --  Thanks to improved error handling support in the underlying c library (libmemcache) we no longer output anything to stderr or stdout which would go straight the the apache log files (or who knows where if you don't use apache and mod_php...).  Now there are more clear errors and warning messages and they are all proper PHP errors.</li>
<li><strong>Fixed memory leak in multiget</strong> -- Only a leak during a single request as php's GC would cache it and clean it up at the end of a request, but if you did many multi-gets per request and many missed (leaked only on a miss), then you could run out of memory during the request.</li>
</ul>

<h3><a href="./php-mcache-ext-1.1.4.tar.gz">mcache extension 1.1.4</a></h3>
<p>Changes</p>
<ul>
<li><strong>Fixed segfault in $mc->stats() when no servers exist</strong> --  When no valid servers exist libmemcache returns a null pointer for the version string.  This was not previously checked for and would result in a segfault when it was copied to a php associative array.  Now this is detected and handled appropriately.</li>
</ul>

<h3><a href="./php-mcache-ext-1.1.3.tar.gz">mcache extension 1.1.3</a></h3>
<p>Changes</p>
<ul>
<li><strong>Fixed lazy memory freeing for serialization</strong> --  When serializing complex objects for storage a php_smart_str is created, in prior releases this was not explicitly freed and relied on php's garbage collection.  This would result in increased memory usage during page execution if a large number of objects were serialized, and would result (in some configurations) in some warnings from php regarding the issue.  However it would never cause a true leak, as php would always cleanup the memory at the end of a rquest.  This memory is now freed as soon as it is no longer needed to both save memory and avoid the warnings.</li>
</ul>

<h3><a href="./php-mcache-ext-1.1.2.tar.gz">mcache extension 1.1.2</a></h3>
<p>Changes</p>
<ul>
<li><strong>Persistent objects leaking fixed</strong> --  When storing persistent objects an internal key is designated, with a pre-pended namespace plus the unique id passed from php, the internal memory for this was set using snprintf, but the length argument to snprintf was uninitialized!  As such, sometimes the key would be truncated, resulting in the creation of new objects with a different key, this would lead to a large number of connections over time.</li>
</ul>

<h3><a href="./php-mcache-ext-1.1.1.tar.gz">mcache extension 1.1.1</a></h3>
<p>Changes</p>
<ul>
<li><strong>Memory Corruption error in persistent objects fixed</strong> --  I had attempted to only allocate persistent memory for non request specific data, but due to the implementation details in libmemcache this was causing the per server buffers to sometimes use the persistent and somtimes the non-persistent allocators if you were using a persistent object.  The result was a segfault if your data was bigger than your buffer.</li>
</ul>

<h3><a href="./php-mcache-ext-1.1.0.tar.gz">mcache extension 1.1.0</a></h3>
<p>Changes</p>
<ul>
<li><strong>Flags field is no longer user accessible</strong> --  It is used internally to keep track of types and serialization.  There was previously an inconsistency in that users were allowed to pass it to set(), add(), and replace(), but their values would sometimes get changed, and they could not get() the flags back anyway.  If you want to use this type of functionality do something like $mc->set('key', Array('val'=>$myvalue, 'flags'->$myflag));</li>
<li><strong>Long, Double, and Bool Types restored correctly</strong> -- A bug in 1.0.0 caused these to all return as strings.  Due to the dynamic typing of php this probably didn't create a real problem for anyone.  But now all types should return exactly as stored.</li>
<li><strong>Persistent memcache objects/connections implemented</strong> -- See example documentation below.</li>
</ul>

<h3><a href="./php-mcache-ext-1.0.tar.gz">mcache extension 1.0.0</a></h3>
<p>Changes</p>
<ul>
<li><strong>Intial Public Release</strong></li>
</ul>

<a name="errata" />
<h2>Errata</h2>

<h3>Known issues</h3>
<ol>
<li>None at this time.</li>
</ol>

<h3>Future plans</h3>
<ol>
<li>Nothing at the moment... <a href="mailto:johnm@klir.com">send requests to me</a></li>
</ol>

<a name="install" />
<h2>Installation</h2>

<p>
In order to install the <a href=".">mcache</a> extension follow the following steps.
</p>

<h3>Installing as a module -- Recommended method</h3>
<ol>
<li>Download and install (following the provided instructions) the latest libmemcache source from <a href="http://people.freebsd.org/~seanc/libmemcache/">people.freebsd.org/~seanc/libmemcache/</a> and extract it to some path.  As of this writing the current version (which the mcache ext is tested against) is 1.3.0 beta7.</li>
<li>Download and extract the php-mcache tarball to some directory</li>
<li>Enter the created php-mcache source directory</li>
<li>Execute the 'phpize' command, this will cause php to create its neccessary build related files to compile an extension on your system.</li>
<li>Execute './configure --with-mcache', you may optionally supply a path for the libmemcache source with --with-mcache=/path/here, but this should normally not be neccesary if you have installed libmemcache to the standard location on your system.</li>
<li>Execute 'make'</li>
<li>Optionally execute 'make install' to automatically install mcache.so to the appropriate php modules directory.  If you do not have priveledges to install modules, you may copy the mcache.so to your own location and load it dynamically on a script by script basis, but this is discouraged for performance reasons.</li>
<li>If you installed the module in the above step then add 'extension=mcache.so' to your php.ini file, and restart your web server, otherwise use dl('/path/to/module/mcache.so'); in your php scripts.</li>
</ol>

<h2>Old Installation, prior to version 1.2.0 beta6</h2>

<h3>Installing as a module -- Recommended method</h3>
<ol>
<li>Download the latest libmemcache source from <a href="http://people.freebsd.org/~seanc/libmemcache/">people.freebsd.org/~seanc/libmemcache/</a> and extract it to some path.  As of this writing the current version (which the mcache ext is tested against) is 1.2.3.</li>
<li>Extract the source tarball to some directory.</li>
<li>Enter the created mcache directory.</li>
<li>Execute the 'phpize' command, this will cause php to create its neccessary build related files to compile an extension on your system.</li>
<li>Execute './configure --with-mcache=/path/to/libmemcache-source'</li>
<li>Execute 'make'</li>
<li>Optionally execute 'make install' to automatically install mcache.so to the appropriate php modules directory.  If you do not have priveledges to install modules, you may copy the mcache.so to your own location and load it dynamically on a script by script basis, but this is discouraged for performance reasons.</li>
<li>If you installed the module in the above step then add 'extension=mcache.so' to your php.ini file, and restart your web server, otherwise use dl('/path/to/module/mcache.so'); in your php scripts.</li>
</ol>

<h4>Compiling directly into PHP -- Not generally recommended</h4>
<ol>
<li>Download the latest PHP source code from <a href="http://www.php.net">www.php.net</a>.</li>
<li>Extract the PHP source to a directory.</li>
<li>Download the latest libmemcache source from <a href="http://people.freebsd.org/~seanc/libmemcache/">people.freebsd.org/~seanc/libmemcache/</a> and extract it to some path.  As of this writing the current version (which the mcache ext is tested against) is 1.2.3</li>
<li>Extract the mcache source tarball to the directory: php-source-dir/ext/mcache/</li>
<li>From the root of the php source directory structure execute './buildconf', you may be told that you need the --force flag if you are using a release package of the php source, if so execute './buildconf --force'</li>
<li>Execute ./configure --with-mcache=/path/to/libmemcache-source (and any other flags you need to pass regularly for your standard php build)</li>
<li>Execute 'make', and 'make install' to install php normally, restart your web server if neccessary.</li>
</ol>

<a name="usage" />
<h2>Example Usage</h2>
<pre>
&lt;?php
	/**
	 * The memcache() function is a factory function that returns a newly
	 * instantiated Memcache object.
	 *
	 * If an internal error prevents creation of a new object FALSE will be 
	 * returned, however under normal circumstances this should never fail.
	 */
	$mc = memcache();

	/**
	 * The add_server() method takes 2 arguments, first the hostname of the server, 
	 * and second the port on which it is listening.
	 *
	 * This method may be called multiple times to add any number of servers.  The extension
	 * will then hash keys in order to decide which server should be used for a given key.
	 *
	 * add_server() returns TRUE on success, and FALSE on failure.  Because an actual 
	 * connection is not immediately attempted, this should always return TRUE except
	 * in the event of an internal error.
	 */
	$mc->add_server('localhost', '11211');
	$mc->add_server('localhost', '11212');

	/**
	 * Another option to the above memcache() and add_server() calls is to use a persistent
	 * memcache object.  This is done by using pmemcache() to initially create the object. 
	 * pmemcache() takes 1 or 2 arguments.  The first argument is required and is a string
	 * that uniquely identifys the object, any future pmemcache() call with the same string
	 * will reuse the persistent object.  The second value is an optional number of seconds,
	 * if the number is > 0 then it will be an expiration on the persistent object.
	 *
	 * Expirations, are useful in scenarios where you have memcache servers sometimes dying. 
	 * Imagine that you have 3 servers, and one goes down.  You want to use a persistent connection
	 * because otherwise each new page is going to result in waiting for a connection timeout,
	 * but at the same time sooner or later you want to retry to see if the server is back up.
	 * As such, say you decide you want to retry every 5 minutes, set the expiration passed to
	 * pmemcache() to 300, and then the object and the 3 server connections will be cached and 
	 * reused for 300 seconds, but after that destroyed and recreated, and as such you will retry
	 * the server.
	 */
	$mc = pmemcache('my_unique_mc_object', 300); // keep it persistent for 5 minutes

	/**
	 * After creating a persistent object, you may or may not need to add servers.  You only
	 * want to add them if the object is newly created, and has not yet been initialized, check
	 * as follows.
	 */
	 if(!$mc->is_initialized()) {
		$mc->add_server('localhost', '11211');
		$mc->add_server('localhost', '11212');

		/**
		 * Now that you are done initializing mark the object as initialized so that on
		 * the next page load you don't repeat the server adds.
		 */
		$mc->set_initialized(TRUE);
	 }


	$fruit_colors = Array('apple'=>'red', 'orange'=>'orange', 'lemon'=>yellow);

	/**
	 * The set() method takes 2-3 arguments, the first argument is the key and is required,
	 * the second is the value associated with the key and is also required.  
	 * 
	 * The fourth is an expiration value  to pass to the server.  This defaults to 0 when unset.  
	 * A 0 expiration means the data never expires.
	 *
	 * add() and replace() methods are also provided, these take the same arguments, the only
	 * difference in functionality is that an add() call will only succeed if the item is not already
	 * in the cache, and a replace() call will only succeed if the item is already in the cache.  
	 * set() always succeeds assuming a memcache server was reachable.
	 *
	 * add(), set(), and replace() all return TRUE on successful addition to the cache, and FALSE on 
	 * failure.
	 */
	$mc->set('fruit_colors', $fruit_colors);

	/**
	 * The get() method takes either a single string as an argument (the key to retrieve),
	 * or an array of strings (multiple keys to retrieve).
	 *
	 * If a single string was passed, then the function returns the value found in the cache,
	 * or FALSE for a cache miss.  If FALSE is the value stored in the cache, then it is 
	 * indistinguishable, from a miss, if you need to store FALSE in the cache, then you should
	 * pass an Array() with just one string in it to get() in order to trigger the 
	 * behavior listed below.
	 *
	 * When the passed argument was an array, the return value will be an array as well.  
	 * This array will contain an entry for each key that was successfully found in the cache.
	 * If a miss occurs, then there will simply be no entry in the array for the key. So imagine
	 * you call ->get(Array('key1', 'key2', 'key3')); If key1 and key3 are found, but key2 is a 
	 * miss the return value is Array('key1'=>'key1 value', 'key3'=>'key3 value'); 
	 */
	$fruit_colors = $mc->get('fruit_colors');
	if($fruit_colors) {
		echo 'Found fruit colors in cache!';
	} else {
		echo 'Cache miss for fruit colors!';
	}

	$request = Array('fruit_colors', 'fruit_prices');
	$results = $mc->get($request);

	if(isset($results['fruit_colors'])) {
		$fruit_colors = $results['fruit_colors'];
	} else {
		//get fruit colors from other source
	}

	if(isset($results['fruit_prices'])) {
		$fruit_prices = $results['fruit_prices'];
	} else {
		//get fruit prices from other source
	}

	/**
	 * The delete() method takes 1 or 2 arguments, the first argument is required
	 * and is the key to delete.  The second is a 'hold time' that tells the cache
	 * not to allow the key to be set again for a certain number of seconds.  By 
	 * default there is no hold time.
	 *
	 * The method returns TRUE when a key is successfully deleted, or FALSE when it is not.
	 */
	$mc->delete('fruit_colors');

	/**
	 * The flush_all() method deletes all keys from all active servers. It takes no
	 * arguments.
	 *
	 * The method returns TRUE except in the case of an internal error preventing
	 * successful flushing, it then returns FALSE.
	 */
	$mc->flush_all();

	/**
	 * The stats() method takes no arguments and returns an associative
	 * array with various statistics related to the cache.
	 */
	$stats = $mc->stats();
	var_dump($stats);

?&gt;
</pre>

<a name="performance" />
<h2>Performance</h2>

<p>
The mcache extension is very fast.  Below are benchmarks that I ran on a Dual CPU Xeon 3.0ghz system running linux 2.6.7.  These benchmarks were with version 1.0.0 of the extension, and linked against the 1.2.1 release of libmemcache.
</p>

<h3>mcache php extension</h3>
<p>
<a href="./test_mcache.phps">Source code for benchmark</a>
</p>
<pre>
Benchmarking libmemcache based mcache client...
Performed 40000 sets in 2.4422888755798 seconds.
Performed 40000 gets in 2.5485188961029 seconds.
Performed 20000 gets of 2 values at once in 1.390410900116 seconds.
</pre>

<h3>libmemcache in c directly</h3>
<p>
<a href="./test.c">Source code for benchmark</a>
</p>
<pre>
Benchmarking libmemcache in c directly...
Performed 40000 sets in 2.248915 seconds.
Performed 40000 gets in 2.234578 seconds.
Performed 20000 gets of 2 values at once in 1.205434 seconds.
</pre>

<h3>PECL memcache extension</h3>
<p>
<a href="./test_pecl_memcache.phps">Source code for benchmark</a>
</p>
<pre>
Benchmarking PECL memcache client...
Performed 40000 sets in 2.7436048984528 seconds.
Performed 40000 gets in 2.7501339912415 seconds.
Performed 20000 gets of 2 values at once in 1.6945209503174 seconds.
</pre>


<a name="license" />
<h2>Licensing</h2>
<p>
This extension is released under the <a href="http://www.php.net/license/2_02.txt">PHP license</a>.  I make no guarantees as to the correctness or safety of the extension.  All use is at your own risk.  I'd appreciate getting sent patches and bug fixes, and if you are using the extension I'd love to hear from you.  However, you are free to use the extension as you wish and are not required to contribute anything back.
</p>

<p>This page is graciously hosted by my employer <a href="http://www.klir.com">Klir Technologies</a>, they likewise accept no liability for this extension, and make no guarantees to its reliability.  If you are interested in a better way to monitor, alert, and report on utilization and availability of your critical network and server infrastructure check out our offerings at the <a href="http://www.klir.com">www.klir.com</a>.  Or, if you are a top notch PHP, C, or C++ developer who is interested in job opportunities then <a href="mailto:jobs@klir.com">send us a resume</a>.
</p>

</body>
</html>