PhilFlash

Flex HTTPService performance with MySQL and PHP: XML : 1 - AMF : 0

French version - Traduire/Translate (by Google): Espagnol - Deutsch

We present various methods to improve the performance of reading XML through an HTTPService.

See the demo

View the sources

Updated : 4 may 2010 see History

Obtenir les sources PerfReadXML.zip - 6 081 Ko (Flex 3 Export Project with Zend Framework 1.10.4 minimal)

Obtenir les sources PerfReadXMLnozend.zip - 500 Ko (Flex 3 Export Project without Zend Framework)

Start application

This article compares 9 methods for reading data (consist of 1 000 to 10 000 records) to fill a datagrid.

A record is a customer described by a id, a lastname, a firstname, gender (male/female), a address and a city.

The tests use a MySQL database (to store data) and the PHP language to write Web-Services on an Apache server.

Optimizations concern the Flex part and the flow between server and browser. Access to data in MySql are the same for all examples.

All the tests use a shared hosting (a 240plan in OVH - phpinfo) that allows the manipulation of the .htaccess file.
If you have a private or dedicated server, it's recommended to modify the httpd.conf file.

The "basic" method with XML nodes : e4x_node

To represent the data, we use XML nodes. Here is how a customer is described:

<customer>
    <id>1</id>
    <lastname>Deschamps</lastname>
    <firstname>Amandine</firstname>
    <sex>1</sex>
    <address>23, rue de la Lancette</address>
    <city>Yerres</city>
</customer>

In Flex, we use a HTTPService component to read data. The data are transformed into Flex objects and we displays them in a Datagrid via a dataProvider (ArrayCollection).

Disadvantage: For a data (name of customer), the names of XML nodes are (sometimes) bigger than the data itself. For example: we use <lastname>Deschamps</lastname> (30 characters) for the lastname Deschamps (9 characters).

The method with XML attributes : e4x_attribute

The idea behind this method is to use attributes instead of nodes and see the impact on the performance.

Here is how a customer is described:

<customer id="1" lastname="Deschamps" firstname="Amandine" sex="1" address="23, rue de la Lancette" city="Yerres"/>

Disadvantage: For a data (name of customer), the names of XML attributes are (sometimes) bigger than the data itself. For example: we use lastname="Deschamps" (20 characters) for the lastname Deschamps (9 characters).

The method with short attributes : e4x_short_attribute

In this method, we use attributes with short names: 1 to 2 letters.

A customer is represented as follows:

<c id="1" ln="Deschamps" fn="Amandine" s="1" ad="23, rue de la Lancette" ci="Yerres"/>

Enable XM compression

When you have 1000 to 10000 records, a good pratice is to compress the XML file between the server and browser. It's a speed tip proposed by pageSpeed of Google.

For this, we enable dynamic compression of Apache. On a shared server, we modify the .htaccess file in the directory of web-services to activate mod_deflate.

In our example, we enable compression for text/xml and application/xml MIME type and disable compression for image:

<IfModule mod_deflate.c>
    SetOutputFilter DEFLATE
    # Insert filter on selected content types only
    AddOutputFilterByType DEFLATE text/xml
    AddOutputFilterByType DEFLATE application/xml
    # Don't compress images
    SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
    # Make sure proxies don't deliver the wrong content
    Header append Vary User-Agent env=!dont-vary
</IfModule>

We will use the 3 methods above to see the performance impact:
e4x_node_gzip
e4x_attribute_gzip
e4x_short_attribute_gzip

How to check if compression is enable or not ?

For this, we use Firefox and theHttpFox extension : an HTTP analyzer to watch request and response headers.

Just manually browse the web service and check the answer with this extension:

http://www.inwayvideo.com/xmlperf/ws_gzip/gzipcustomerAttribute.php

Check gzip for Content-Encoding in Response Header

Compression gzip

 

Content type application/xml, text/xml and browser cache : e4x_cache_attribute_gzip

If your data aren't modified very often (every 4 hours or days or weeks or months), the idea is to use the browser's cache to store query results.

An HTTPService with POST mode forces a refresh for a page: the results will not be kept in the browser cache.

The idea is to use the GET method. But there is a subtlety in Flex. If you use the contentType (or MIME type) text/xml, Flex converts the GET method in POST method (and thus prevents the browser from storing the result in the cache). See the send method in mx.rpc.http.HTTPService (in Flex 3 SDK and SDK 3.3) or sendBody method in mx.rpc.http.AbstractOperation (in Flash Flash Builder 4 and SDK 3.5.0)

     if (contentType == CONTENT_TYPE_XML && message.method == HTTPRequestMessage.GET_METHOD)
         message.method = HTTPRequestMessage.POST_METHOD;

To activate the browser's cache, you must use the GET method with contentType text/xml.

If you have a sharing hosting, check the compression for the different MIME types. At OVH, the compression is enabled for application/xml but the compression is disabled for text/xml.

To enable the compression for text/xml and application/xml and have a cache of 30 minutes, configure the .htaccess file in the web-services directory as follows :

<IfModule mod_deflate.c>
    SetOutputFilter DEFLATE
    # Insert filter on selected content types only
    AddOutputFilterByType DEFLATE text/xml
    AddOutputFilterByType DEFLATE application/xml
</IfModule>

<IfModule mod_expires.c>
    #CACHE ExpiresActive on
    #xml
    ExpiresByType text/xml "access plus 30 minutes"

    #tout le reste
    #ExpiresDefault "modification plus 2 years"
    ExpiresDefault "access plus 2 days"

</IfModule>

This is the fastest method. With this method, click twice on the button. During the second click, the cache of the browser is used.

Method Amfphp : amfphp

Amfphp has been the first open-source solution using the protocol AMF (Action Message Format) on PHP.

Unfortunately, this project is no longer maintained. This project has a new version. The advantage of this method is to use a class mapping between PHP and Flex (to avoid encoding and decoding between the different languages).

In our example, we use amfphp 1.9 version of 2010-02-02.

Method Zend-AMF : zend_amf

This method uses Zend-AMF. As in AMFPHP, we use the class mapping between PHP and Flex.

In our example, we use Zend Frameword version 1.9.7 1.10.4

Unfortunately, it's a "bad" good idea. Performances are not at the rendez-vous.

To try to improve performance, we use another method (zend_flex4). This method is based on the generated code in Flex 4 and gives better performance. This solution use the cast of the results in PHP with Zend-AMF (this method has no impact on the performance with amfphp).

For information, version 1.10.4 contains a patch to improve the performance of Zend AMF:
http://framework.zend.com/changelog/1.10.4
The performance is actually improved but are below AMFPHP and XML.

The Zend Framework is very interesting when you develop PHP applications, but on this particular example, we have performance problems on a shared server.

For performance problems with Zend-AMF, see :
http://framework.zend.com/issues/browse/ZF-7493

If you are an expert on AMF or Zend, don't hesitate to send me your tips to improve performance.

Results

You can test the application directly on our server and you will see that the fastest method is e4x_short_attribute_gzip.

Indeed, the Flash Player has a very efficient reader for XML with E4X.

Th browser's cache improves performance with the e4x_cache_attribute_gzip method. But that's normal: it uses the browser cache.

XML Performance

 

Installation on your server

To test the different methods on your server :

- Install the xmlperf directory on your PHP server (PHP5 is required).
- Configure the xmlperf/xmlperfDefine.php file:

- Run in your browser: http://www.myserver.com/xmlperf/generateDb/generateCustomer.php
This will generate MAXIMUM_RECORDS in your database.
The script takes about between 30 seconds and 1 minute.

- Run in your browser: http://www.myserver.com/xmlperf/flex
This allows to test different methods.

Sources

Sources files for Flex and PHP are delivered.

Flex

If you install the sources on your server, modify the serverURL variable in initApp and the two uri variables in the services-config.xml file (for amfphp and Zend Framework).

In Flex, we use a Customer class for XML. For class-mapping (for AMF), we use a CustomerVO class.

PHP

Each method uses a directory with ws prefix (for Web-services). Each directory contains the files called by the HTTPService component.
The directories are:

ws_nogzip : methods without compression:

ws_gzip : method with gzip compression

ws_amfphp : for amfphp.

- add two files into xmlperf/ws_amfphp/services directory: CustomerService.php and inway/CustomerVO.php.
- modify xmlperf/ws_amfphp/globals.php file to configure $voPath variable (for class-mapping)
- modify xmlperf/ws_amfphp/gateway.php for UTF-8 charset with $gateway->setCharsetHandler("iconv","UTF-8","UTF-8"); (assuming that iconv is installed on the server).

ws_zend : for Zend AMF

- add two files: CustomerService.php and gateway.php (for service and and class-mapping).

References and link

census: Ajax and Flex Data Loading Benchmarks from James Ward. In this test, AMF is the fastest method (but the method based on XML uses nodes and no compression).
http://www.jamesward.com/2007/04/30/ajax-and-flex-data-loading-benchmarks/

Zend AMF: http://framework.zend.com/download/latest (use zend framework version "1.x.x minimal" at the bottom of the page)

Wade Arnold blog author of Zend AMF
http://wadearnold.com/blog/

Get to know Flex and Zend_Amf (Zend developper zone)

Data-centric Adobe Flash Builder development with the Zend Framework (Zend developper zone)

Amfphp: http://www.amfphp.org/

Flex + AMFPHP: Mapping Value Objects

AMFPHP and MySQL character set

Sean Christmann: Optimizing Adobe AIR for Code Execution, Memory, and Rendering

MySQL Performance Blog: http://www.mysqlperformanceblog.com

Optimizing and configuring Apache: http://www.askapache.com/

History

version 1.02 - 4 May 2010

- updated to Zend Framework version 1.10.4 (Released 2010-04-28)
   This version has a patch for Zend AMF performance issue
- updated to amfphp 1.9 (Released 2010-02-02)

version 1.01 - 14 January 2010

- updated to Zend Framework version 1.9.7

version 1.00 - 10 January 2010

- Initial release with :
. amfphp 1.9 beta2 - 2008-01-20
. Zend Framework 1.9.6

xhtml   css   cc   508   aaa
Me connaître  |  Me contacter