Posted on: April 19, 2006 in PHP

Speeding up XML-RPC calls in Drupal

Through Bryght, I’ve been working on an interesting project that really exercises the “toolkit” and “web services platform” like nature of Drupal. The final architecture of our project ended up having many distributed processes, all sending data to Drupal through XML-RPC, and we were using Drupal mainly to aggregate and display the results.

Performance was very important, and we were having a huge bottle neck with Drupal’s XML-RPC library. XML-RPC calls were talking a long fricken time, and we were making tons of them.

Fortunately I had help from Walkah and Moshe, and I thought I would pass on what we did to drastically increase XML-RPC performance. This worked for us, so maybe it might help someone else out.

The problem is of course that Drupal does a full bootstrap for every XML-RPC call.

Our solution:
The first, simple (and huge) win was to utilize a PHP opcode cacher - this drastically reduces this bootstrapping time. We used eAccelerator, but there are many others.

Secondly, since we were working in a controlled environment (we knew what modules were going to be called via XML-RPC) we were able to hack the xmlrpc.php file to avoid a full bootstrap. The downside is we had to hardcode a few path things into the file, but again, this is for a particular app/site, and the performance gains were worth it.

Courtesy of Moshe, here is our revised xmlrpc.php file (you might want to rename it to xmlrpcs.php or something):


< ?php
// $Id$

/**
* @file
* Optimized php page for handling xml-rpc requests. Your module must use declare the hook_init() or hook_exit()
* so that it is loaded during the boostrap. Otherise, use hook_xmlrpc as usual. Note that only required modules are loaded at this point.
*
* @author
* Moshe Weitzman
*/

// CONFIGURE
$path = ‘./sites/mwpb-9.local/modules/’;
$module = ‘my-xmlrpc-module’; //the name of the module where your xml-rpc calls are
// END CONFIGURE

include_once ‘./includes/bootstrap.inc’;
drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE);
include_once ‘./includes/xmlrpc.inc’;
include_once ‘./includes/xmlrpcs.inc’;

require_once $path. $module. ‘.module’;
$function = $module. ‘_xmlrpc’;
$callbacks = $function();
// print_r($callbacks);
xmlrpc_server($callbacks);

// put any common.inc or other core functions here that your module relies upon.
function t($string) {
return $string;
}
?>

This was enough to get a huge increase in performance. (Yeah!)

Further thoughts:
One could use “mysql_query()” and avoid bootstrap all together, although I don’t think this is very much overhead, and the benefits of using Drupal’s “Database abstraction layer” probably out way any performance overhead here.

I wonder if there is any way to get Drupal to intelligently load necessary code instead of doing a full bootstrap. The “hardcoding” method above certainly works, but I am craving a more elegant and universal solution. Any thoughts?

Leave a Reply