Pages

Showing posts with label php. Show all posts
Showing posts with label php. Show all posts

9 Jun 2011

Video uploading guide

#1 Introduction

This document provides information about setting up video uploading and streaming for PHP based websites. This guide has been prepared by studying various resources from Internet hence this is tried and tested and almost de-facto standard in video uploading, processing and streaming.

#2 Video uploading stages

There are 3 stages in video uploading viz. Uploading video, Processing it for streaming and Streaming.

#2.1 Uploading video

Generally video files are large in terms of file size hence separate page/interface is designed to handle long uploading process. By this interface, user can send their video to your server for streaming attached to ad.

#2.2 Processing video

Processing video involves activities such as creating video thumbnails (for promotion, preview etc.), converting video formats suitable for various browsers, extracting meta-data from video for various purposes.

#2.3 Streaming video

In 3rd stage, converted videos are streamed through flash player or by browser's built in media players supporting those video types.

#3 Implementation guidelines

This guidelines mainly emphasizes on set up of web server because it is the most important part and 99% remain same for most of video uploading and streaming purpose; processing and streaming is less critical since it varies from project to project.

#3.1 Uploading video

To upload various types of videos, we first need to set up webserver so that it can accept video files. It is also better to have separate machine for video uploading, processing and streaming so that website which used those videos will not share load given by video related operations as such operations heavily consumes memory and CPU.

In this article I have decided to use Lighttpd 1.5 as video uploading and streaming server mainly for 2 reasons:
  1. it is specially designed to serve static contents,
  2. it has such modules/plugins which provides information about uploading progress directly to caller script which is very convenient to developers to design interface with minium coding.
There are 2 alternating solutions also viz. Apache + apache-upload-progress-module and Nginx + nginx-upload-progress-module & nginx-upload-module. However there is not much feedback available about these 2 solutions, hence I decided not to use them and sticked to lighttpd since it is popular and trusted.

#3.1.1 Installing and configuring Lighttpd

For rpm based distributions, use following command to install lighttpd server related packages:

yum install pcre-devel glib2-devel zlib-devel openssl-devel spwan-fcgi php php-cli

Lighttpd 1.5 is not yet available in any yum repository hence we have to compile and configure it manually as shown below:
  • Download lighttpd.
cd /tmp/
wget http://download.lighttpd.net/lighttpd/snapshots-1.5/lighttpd-1.5.0-r2698.tar.gz
tar -zxvf lighttpd-1.5.0-r2698.tar.gz
cd lighttpd-1.5.0
  • Configure and install
./configure --program-prefix= --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --sysconfdir=/etc --datadir=/usr/share --includedir=/usr/include --libdir=/usr/lib --libexecdir=/usr/libexec --localstatedir=/var --sharedstatedir=/usr/com --mandir=/usr/share/man --infodir=/usr/share/info --with-pcre

make
make install
  • Add necessary user/group, directories and files
adduser -m -d /var/www -s /sbin/nologin lighttpd
mkdir /etc/lighttpd/
mkdir -p /www/logs/
mkdir -p /web/pages/
chown lighttpd:lighttpd /var/log/lighttpd
cp doc/lighttpd.conf /etc/lighttpd/
  • Make changes as per your setup by editing “/etc/lighttpd/lighttpd.conf” file
server.modules = ("mod_rewrite",                  "mod_access",
                  "mod_status",
                  "mod_uploadprogress",
                  "mod_proxy_core",
                  "mod_proxy_backend_fastcgi"
                  "mod_accesslog"
                )

server.max-request-size = 150000  // to support approx 120/150 MB of file.
upload-progress.progress-url = "/progress"
upload-progress.remove-timeout = 10

#### mod-proxy-core module
## read mod-proxy-core.txt for more info
## for PHP don't forget to set cgi.fix_pathinfo = 1 in the php.ini
$PHYSICAL["existing-path"] =~ "\.php$" {
  proxy-core.balancer = "round-robin"
  proxy-core.allow-x-sendfile = "enable"
  proxy-core.protocol = "fastcgi"
  proxy-core.backends = ( "unix:/tmp/php-fastcgi.sock" )
  proxy-core.max-pool-size = 16
}

# setup of host specific to video upload.
$HTTP["host"] =~ "video.myproject.com" {
  server.document-root = "/web/video.myproject.com"
  server.errorlog = "/web/logs/video.myproject.com_error.log"
  #accesslog.filename = "/web/logs/video.myproject.com_access.log"
  server.error-handler-404 = "http://www.myproject.com"

  $HTTP["url"]  =~ "^/upload" {
    proxy-core.balancer = "round-robin"
    proxy-core.protocol = "fastcgi"
    proxy-core.allow-x-sendfile = "enable"
    proxy-core.backends = (
      "unix:/tmp/upload_socket_1.sock",
      "unix:/tmp/upload_socket_2.sock",
      #"unix:/tmp/upload_socket_N.sock",
    )
    proxy-core.max-pool-size = 2  # as per backend.
  }
}

In above setup, what we are doing is that when video is uploaded to URI upload, we are proxying request to more than 1 socket using fastcgi protocol so that we can handle 2 to N uploads at a time on dedicated unix sockets. We do not need to worry about which socket is to be used and which is not, since webserver handles it on own. You can create more than 2 sockets also to handle more concurrent video uploads.

Here PHP script upload will contain code to move/copy video file at desired location making it available for further processing. This script will be normal PHP CGI script containing valid PHP code. Please note that for copying/renaming etc. you need file name so it is better to pass it from website as hidden variable of the form so that this script can rename video by that name.

Please note that for URI other than upload, dedicated php-fastcgi.sock will be used. Also do not forget to rotate 404 error log :)
  • Verify installation by running following command
lighttpd -t -f /etc/lighttpd/lighttpd.conf
  • Create init.d file “/etc/init.d/lighttpd” as shown below
#!/bin/sh
#
# lighttpd     Startup script for the lighttpd server
#
# chkconfig: - 85 15
# description: Lightning fast webserver with light system requirements
#
# processname: lighttpd
# config: /etc/lighttpd/lighttpd.conf
# config: /etc/sysconfig/lighttpd
# pidfile: /var/run/lighttpd.pid
#
# Note: pidfile is assumed to be created
# by lighttpd (config: server.pid-file).

# Source function library
. /etc/rc.d/init.d/functions

if [ -f /etc/sysconfig/lighttpd ]; then
  . /etc/sysconfig/lighttpd
fi

if [ -z "$LIGHTTPD_CONF_PATH" ]; then
  LIGHTTPD_CONF_PATH="/etc/lighttpd/lighttpd.conf"
fi

prog="lighttpd"
lighttpd="/usr/sbin/lighttpd"
RETVAL=0

start() {
  echo -n $"Starting $prog: "
  daemon $lighttpd -f $LIGHTTPD_CONF_PATH
  RETVAL=$?
  echo
  [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
  /usr/bin/spawn-fcgi -s /tmp/php-fastcgi.sock -f /usr/bin/php-cgi -u lighttpd -g lighttpd -P /var/run/spawn-fcgi.pid
  /usr/bin/spawn-fcgi -s /tmp/upload_socket_1.sock -f /usr/bin/php-cgi -u lighttpd -g lighttpd -P /var/run/upload_socket_1.pid
  /usr/bin/spawn-fcgi -s /tmp/upload_socket_2.sock -f /usr/bin/php-cgi -u lighttpd -g lighttpd -P /var/run/upload_socket_2.pid
  # /usr/bin/spawn-fcgi -s /tmp/upload_socket_N.sock -f /usr/bin/php-cgi -u lighttpd -g lighttpd -P /var/run/upload_socket_N.pid
  return $RETVAL
}

stop() {
  echo -n $"Stopping $prog: "
  killproc $lighttpd
  killproc php-cgi
  RETVAL=$?
  echo
  [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog /tmp/php-fastcgi.sock
/var/run/spawn-fcgi.pid /tmp/upload_socket_1.sock /var/run/upload_socket_1.pid
/tmp/upload_socket_2.sock /var/run/upload_socket_2.pid
  return $RETVAL
}

reload() {
  echo -n $"Reloading $prog: "
  killproc $lighttpd -HUP
  RETVAL=$?
  echo
  return $RETVAL
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  restart)
    stop
    start
    ;;
  condrestart)
    if [ -f /var/lock/subsys/$prog ]; then
      stop
      start
    fi
    ;;
  reload)
    reload
    ;;
  status)
    status $lighttpd
    RETVAL=$?
    ;;
  *)
  echo $"Usage: $0 {start|stop|restart|condrestart|reload|status}"
  RETVAL=1
esac

exit $RETVAL

In above init.d file, I have merged creation of spawn-fcgi process along with lighttpd process because wihout “spawn-fcgi” process your PHP script can not receive data from webserver.
  • Start lighttpd service
chmod +x /etc/init.d/lighttpd
/etc/init.d/lighttpd start

#3.1.2 Creating interface to upload videos

To create interface on your website, follow this best example. It explains how to create HTML form, Jquery based JS code and some basic stylsheets. Please do not forget to validate video file name by extension. If you face cross site domain issue, follow this native example using iframe.

#3.2 Processing video

Once video is copies/moved at desired location, it needs to be processed by a script for various purposes. These operations are like converting video; extract metadata; creating thumbnails; etc. for streaming purpose.

This should be done by separate process script. Let's call it as “process.php” script. But we also need various other software for processing. Install them on video server, using following command:

yum install ffmpeg, flvtool2, compat-readline5, php-gd php-devel libaio-devel

This process.php script will be set into crontab and should run every 1 minute so that newly uploaded videos can be processed as fast as possible.

#3.2.1 Converting video

User might have uploaded videos from any source, so there is no guarantee that it can be played in any browser since all browsers do not support all codecs. Hence we must convert uploaded video into desired format. We decided to use flash format.

Run following command from your php script to convert video into FLV format:

ffmpeg -i INPUT_VIDEO -ar 22050 -ab 32 -ac 1 -f flv -b 700k -r 15 -s ASPECT_RATIO - 2>/dev/null | flvtool2 -U stdin OUTPUT_VIDEO.flv > /dev/null

In above command, we are combining use of flvtool2 to embed keyframe markers for streaming. In your script, you will require to adjust ASPECT_RATIO.

#3.2.2 Creating thumbnails

To extract thumbnail from video file, following command can be used:

ffmpeg -itsoffset -4 -i VIDEO_FILE -vcodec CODEC -vframes 1 -an -f rawvideo -s 320x240 OUTPUT.jpg

This command generates a 320×240 sized JPG thumbnail at the 4th second in the video. You can use this example to randomly create thumbnails according to length of the video.

#3.2.3 Extract metadata

To extract metadata, following command can be used:

ffmpeg -i INPUT_VIDEO

It will print lot of metadata about video in text format which can be stored in database or used while streaming video.

#3.3 Streaming video

Streaming video requires support from webserver, JS, Flash player and some HTML work.

#3.3.1 Preparing server

Lighttpd server has built in streaming support to stream video files. To support streaming using keyframes, enable required module in server “/etc/lighttpd/lighttpd.conf” configuration file:

server.modules += ( "mod_flv_streaming" )
flv-streaming.extensions = ( ".flv" )

Restart web service to reflect above changes. Now server is ready to stream video files in flv format with support of keyframes.

#3.3.2 Streaming through HTML5

There are 2 ways to stream video. They are either using HTML5's native “video” tag or using Flash player as container.

Streaming video through HTML5 is as easy as showing image in browser, but unfortunately not all browsers support HTML5 because their support started to arrive in latest browser only in beginning of year 2011. Moreover even if browser supports HTML5, not all browsers supports all codec (another round of browser war) hence if user uploads video with H.264 codec, it will not be played in firefox and chrome browsers. Similarly if video is encoded using Theora codec then it will not be played in IE. More information about this situation can be found from here.

However if still it is decided to use HTML5 then following HTML tag can be used:

<video src="movie.mpeg" controls="controls">
Fallback flash player based video streaming code.
</video>

That's it, by this way any video file can be played without any JS/HTML code if browser supports video file's codec natively.

#3.3.3 Streaming through Flash player

Unfortunately standard solution is to use Flash player based video streaming method which streams video inside flash container. That is why earlier we had to convert video into “flv” format :). Because flash player natively supports almost all codec.

To stream video using flash container, follow this excellent tutorial.

#4 Improvements
  1. In this article, I have not discussed about realtime video format validation to prevent users from uploading junks.
  2. Since video server mostly serves video files and occasionally JS and HTML, you should deny access for other files than these.
  3. When you will require more features for video processing, streaming you will need  to use wrapper classes like phpvideotoolkit and native ffmpeg-php extension.
#5 Resources

http://flowplayer.org/plugins/streaming/pseudostreaming.html
http://en.wikipedia.org/wiki/Flash_Video#Format_details
http://praegnanz.de/html5video/
http://uakino.net/media/document/1009.pdf
http://diveintohtml5.info/video.html

1 Feb 2010

Quality Assurance guidelines

#1 Introduction

This document provides detailed information about Quality Assurance plan for web based software. Intended audience of this document consists of developers, testing team, project manager, stack-holders and clients.

#2 Quality objectives

To achieve high quality of code and functionality to it's customers, team can design a detailed QA plan to be followed throughout development life cycle and post-development life span. To achieve this aim, following objectives should be  decided by development team.
  • No untested code should be shipped to clients.
  • Test criteria must cover at least 75% of code for testing procedure.
  • Whatever has been tested is documented for various purposes.
  • Each functionality of the software must be tested according to requirement specifications and must run in most popular browsers and platforms in similar way.
#3 Management

#3.1 Team

Quality Assurance team primarily involves Test manager, Developers and Dedicated & Ad-hoc testers. It directly reports to Project manager and/or Development manager.

#3.2 Tasks and Responsibilities

QA team performs following tasks.
  1. Doing unit testing;
  2. Doing functionality testing;
  3. Doing usability testing;
  4. Managing testing documentation;
  5. Managing testing guidelines;
  6. Reviewing test cases;
  7. Doing continuous testing for core code;
  8. Providing training to new members;
Breakdown of above tasks by team members is as follows;
  • Developers do unit testing of code and make sure that it doesn't break even after making changes in it for new/updated features;
  • Dedicated and Ad-hoc testers then test those newly added/updated features in various browsers and tools to make sure that features behave according to requirement specifications;
  • Test manager checks created unit & functional tests and re-run them as and when needed. He also writes complex test cases to test code and features from various aspects like stress, load bearing, sanity etc.
  • Test manager is also responsible for preparing testing plans and guidelines for existing and new testers. Test manager also manages documentation of test cases and suits in repository for proof of quality control and easier access.
  • Development and Test manager together work for running unit tests continuously on test server for consistent quality check.
  • Training to new tester is usually provided by Test manager as and when needed during development life cycle.
Details about each task has been provided in following sections.

#4 Testing overview

Software testing is the process used to help identify the correctness, completeness, security, and quality of developed computer software. Testing is a process of technical investigation, performed on behalf of stakeholders, that is intended to reveal quality-related information about the product with respect to the context in which it is intended to operate.

#4.1 Unit testing

When it comes to source code, unit testing of code is performed in order to be sure that there is no problem at code level. In unit testing, unit is known as a part of code which can be a function, a method or a whole class. In short, unit testing tests code of software into various pieces. Hence successful unit testing shows that software is now ready for functional testing.

PHPUnit is a member of the xUnit family of testing frameworks and provides both a framework that makes the writing of tests easy as well as the functionality to easily run the tests and analyse their results.

#4.2 Functionality testing

Purpose of functionality testing is to test whole system (or software sometimes) using automatic and manual tools. Whole system may include PHP code, JS code, HTML etc. In this type of testing, various components of software are tested together. Software like selenium is used to perform functionality testing.

Selenium IDE is an integrated development environment for Selenium tests. It is implemented as a Firefox extension, and allows you to record, edit, and debug tests.

#4.3 User (Usability) testing

Usability testing is for measuring how well people can use some human-made object (such as a web page, a computer interface, a document, or a device) for its intended purpose, i.e. usability testing measures the usability of the object. Usability testing focuses on a particular object or a small set of objects, whereas general human-computer interaction studies attempt to formulate universal principles. Software like ab and mysqlprofile can be used to perform usability testing.

#5 Deliverables

QA deliverables include testing guidelines, manual and automated test cases, statistical and coverage reports and overall documentation related to QA. These are well organized and kept in version control for concerned project's application.

#6 Testing Guidelines

Testing guidelines and goals help achieve highest standards in quality control. They have been prepared to assist developers and testers to write effective test cases and to document them for various purposes.

#6.1 Unit testing

To read unit testing related guidelines and principles, read section #4 in this document.

#6.2 Functionality testing

To read functional testing related guidelines and principles, read section #4 in this document.

#7 Review process

Review of test cases is checking test cases by test colleagues and/or test manager in order to make sure that those are correct or any misunderstandings in the requirements or anything missed out or not. Since review is a continuous process, test manager regularly checks previously designed test cases and re-run them whenever needed.
  1. Review process comprises following things:
  2. Completeness- Do test cases contain enough conditions of code and features to be tested?
  3. Accuracy- Are test cases accurately defined and logical? Are there missing elements?
  4. Testable- Are test cases testable?
#8 Continuous testing

Continuous testing uses excess cycles on a workstation to continuously run regression tests in the background, providing rapid feedback about test failures as source code is edited. It reduces the time and energy required to keep code well-tested, and prevents regression errors from persisting uncaught for long periods of time.

For more information about continuous testing, please refer this document.

#9 Training

Training is important part of any department during software development life cycle. Test manager regularly provides training to QA team to improve testing procedure and to make it as effective as possible.

#10 References

http://phing.info/trac/
 

17 Jul 2009

PHP project build system

#1 Pre-requisites

Before reading this document, it is required to read unit testing guidelines, which is part of this package.

#2 PHPUnit, CVS and Phing

For a typical web based software, our main requirements are to automate several routine tasks like unit testing, updating latest data from version control, loading packages on different servers, cleaning up log files and performing other daily routine task to save manual work.

Hence here we will have brief look at how Phing can be used to automate some of the above mentioned tasks. But before that let's see what Phing is and how it works.

#2.1 What is Phing

Phing (PHing Is Not GNU make) is a project build system based on Apache Ant. In the context of PHP, where it is not required to build and compile sources, the intention of Phing is to ease the packaging, deployment, and testing of applications. For these tasks, Phing provides numerous out-of-the-box operation modules ("tasks") and an easy-to-use, object-oriented model for adding our own custom tasks.
Phing can be installed using the PEAR Installer, as shown in the following command line:

$ pear channel-discover pear.phing.info
$ pear install phing/phing

For other modes of installation and more details read Phing documentation.
Note: Please do not forget to install other dependencies also that Phing might ask during it's installation.

#2.2 How it works

Phing uses XML buildfiles that contain a description of the things to do. The buildfile is structured into targets (groups of task/s) that contain the actual commands to perform (e.g. commands to copy a file, delete a directory, perform a DB query, etc.). So, to use Phing, we would first write our buildfile and then run phing specifying the target in buildfile that we want to execute.

$ phing -f [mybuildfile.xml] [mytarget]

By default Phing will look for a buildfile named build.xml (so you don't have to specify the buildfile name unless it is not build.xml) and if no target is specified Phing will try to execute the default target, as specified in the tag.

A valid Phing buildfile has the following basic structure:
  1. The document prolog,
  2. Exactly one root element called ,
  3. Several Phing type elements (i.e. , , etc.),
  4. One or more elements containing built-in or user defined Phing task elements (i.e. , , etc).
It is beyond the scope of this document, to explain above structure. Hence please read phing documentation.

#2.3 Phing and automated testing

Phing has several built in tasks to perform various operations. Some of them, for our purpose, are exec, delete, mkdir, coverage-setup, phpunit, phpunitreport and coverage-report.
  1. exec task can be used to execute any command of OS environment and applications;
  2. delete can be used to remove files/folders;
  3. mkdir to make new directories;
  4. phpunit to run unit tests created by developers (as described in this document);
  5. phpunitreport to generate report about unit tests;
  6. coverage-setup and coverage-report tasks are for providing detailed report of code-coverage analysis.
#2.5 Agile documentation

Continuous testing using Phing is performed everyday on test server and 2 types of documentation is generated at following locations for every project;
  1. tests/unittests/reports/index.html and
  2. tests/unittests/reports/coverage/index.html (for reporting purpose)
Since this document is generated anytime on the fly and gets updated after every run, it doesn't require to add them into version control.

#2.6 Guidelines about using Phing
  1. Phing has vast application areas hence in beginning it is used for limited tasks only like updating local repository from CVS, running unit tests, code analysis, packaging and unpacking files etc. Later it will be expanded to handle more complex tasks.
  2. Build management system such as Phing, should not be used by individual developers as it affects whole system. Hence it's care is taken by dedicated test/project/development manager.
  3. Phing can be extended to create custom tasks also. But that requires extensive study of it's existing functionality.
#3 Links

http://phing.info/docs/guide/current/
http://www.phpunit.de/manual/3.3/en/build-automation.html#build-automation.phing

26 May 2009

Unit testing guidelines

#1 Introduction

This document provides detailed information about how to unit test code of PHP based software. Intended audience of this document consists of developers, testing team, project manager and stack-holders.

#2 What is unit testing

Unit testing is a software verification and validation method in which a programmer tests that individual units of source code are fit for use. A unit is the smallest testable part of an application. In procedural programming a unit may be an individual program, function, procedure, etc., while in object-oriented programming, the smallest unit is a class, which may belong to a base/super class, abstract class or derived/child class.

The goal of unit testing is to isolate each part of the program and to show that the individual parts are correct. Unit testing provides a strict, written contract that the piece of code must satisfy. As a result, it affords several benefits. In this article we will follow PHPUnit as a unit testing software.

#2.1 Advantages of unit testing

#2.1.1 Facilitates change

Unit testing allows the programmer to refactor code at a later date, and make sure the module still works correctly (i.e. regression testing). This provides the benefit of encouraging programmers to make changes to the code since it is easy for the programmer to check if the piece is still working properly. Good unit test design produces test cases that cover all paths through the unit with attention paid to loop conditions. In continuous unit testing environments, through the inherent practice of sustained maintenance, unit tests will continue to accurately reflect the intended use of the executable and code in the face of any change. Depending upon established development practices and unit test coverage, up-to-the-second accuracy can be maintained.

#2.1.2 Simplifies integration

Unit testing helps eliminate uncertainty in the units themselves and can be used in a bottom-up testing style approach. By testing the parts of a program first and then testing the sum of its parts, integration testing becomes much easier.

A heavily debated matter exists in assessing the need to perform manual integration testing. While an elaborate hierarchy of unit tests may seem to have achieved integration testing, this presents a false sense of confidence since integration testing evaluates many other objectives that can only be proved through the human factor. Some argue that given a sufficient variety of test automation systems, integration testing by a human test group is unnecessary. Realistically, the actual need will ultimately depend upon the characteristics of the product being developed and its intended uses.

#2.1.3 Documentation

Unit testing provides a sort of "living document". Clients and other developers looking to learn how to use the module can look at the unit tests to determine how to use the module to fit their needs and gain a basic understanding of the API.

Unit test cases embody characteristics that are critical to the success of the unit. These characteristics can indicate appropriate/inappropriate use of a unit as well as negative behaviors that are to be trapped by the unit. A unit test case, in and of itself, documents these critical characteristics, although many software development environments do not rely solely upon code to document the product in development.

Ordinary documentation, on the other hand, is more susceptible to drifting from the implementation of the program and will thus become outdated (e.g. design changes, feature creep, relaxed practices to keep documents up to date).

#2.1.4 Separation of interface from implementation

Because some classes may have references to other classes, testing a class can frequently spill over into testing another class. A common example of this is classes that depend on a database: in order to test the class, the tester often writes code that interacts with the database. This is a mistake, because a unit test should never go outside of its own class boundary. As a result, the software developer abstracts an interface around the database connection, and then implements that interface with their own mock object. This results in loosely coupled code, minimizing dependencies in the system.

#2.2 Limitations of unit testing

Unit testing will not catch every error in the program. By definition, it only tests the functionality of the units themselves. Therefore, it will not catch integration errors, performance problems or any other system-wide issues. In addition, it may not be easy to anticipate all special cases of input the program unit under study may receive in reality. Unit testing is only effective if it is used in conjunction with other software testing activities.

It is unrealistic to test all possible input combinations for any non-trivial piece of software. A unit test can only show the presence of errors; it cannot show the absence of errors. Though these two limitations apply to any form of software test.

#3 PHPUnit

PHPUnit is an excellent unit testing software for PHP programming language based softwares, which is derived from JUnit software (in Java technology). To learn PHPUnit, well understanding of OOP is must.

Testing with PHPUnit is not a totally different activity from what you should already be doing. It is just a different way of doing it. The difference is between testing, that is, checking that your program behaves as expected, and performing a battery of tests, runnable code-fragments that automatically test the correctness of parts (units) of the software. These runnable code-fragments are called unit tests.

It is to be clearly kept in mind that unit testing should be performed as soon as coding is finished, and not after days and month. When software's code gets changed, corresponding tests should also get changed and tested.

#3.1 How PHPUnit works

PHPUnit API has several built in methods to perform various kind of testing on your given code. Developer first write certain code according to requirement of software. Then he will need to create certain test cases (or suits) using PHPUnit's built in classes and finally to test those test cases (or suits) to be sure that designed code works properly.
  1. Test cases (or suits) are nothing but PHP scripts that test code of software using PHPUnit's built in tests. Hence there are 3 components in unit testing:
  2. Software's code
  3. PHPUnit's built in tests and
  4. Test cases (or suits).
#3.2 Installing PHPUnit

PHPUnit should be installed using the PEAR Installer. This installer is the backbone of PEAR, which provides a distribution system for PHP packages, and is shipped with every release of PHP since version 4.3.0.

The PEAR channel (pear.phpunit.de) that is used to distribute PHPUnit needs to be registered with the local PEAR environment:

$ pear channel-discover pear.phpunit.de

This has to be done only once. Now the PEAR Installer can be used to install packages from the PHPUnit channel: 

# pear install phpunit/PHPUnit


After the installation you can find the PHPUnit source files inside your local PEAR directory; the path is usually /usr/lib/php/PHPUnit.

Although using the PEAR Installer is the only supported way to install PHPUnit, you can install PHPUnit manually. For manual installation, do the following:
  • Download a release archive from http://pear.phpunit.de/get/ and extract it to a directory that is listed in the include_path of your php.ini configuration file.
  • Prepare the phpunit script:
Rename the phpunit.php script to phpunit.
Replace the @php_bin@ string in it with the path to your PHP command-line interpreter (usually /usr/bin/php).
Copy it to a directory that is in your path and make it executable (chmod +x phpunit).
  • Prepare the PHPUnit/Util/Fileloader.php script:
Replace the @php_bin@ string in it with the path to your PHP command-line interpreter (usually /usr/bin/php).
After successful installation of PHPUnit, you can use command phpunit /PATH/TO/TESTSCRIPT to run your tests. For all the available options of this command type phpunit -–help.

#3.3 How to learn and use PHPUnit

Road map of learning and using PHPUnit has been shown below.
  1. Get good understanding of OOP.
  2. Read whole documentation of PHPUnit software to understand what it is and how it works.
  3. Install PHPUnit to build up testing environment.
  4. Study code of all scripts of PHPUnit software even if at first time, you don't understand much.
  5. Having look at the testing examples provided by PHPUnit, understand how unit testing works.
  6. Now try to build your own test cases of software on which you are working.
  7. After having enough experience of building test cases, try to build test suit that can perform all test at once (which is the goal of the unit testing).
  8. Try to build more complex and fully automated test suits using PHPUnit's extensions and other utilities or by building your own custom extensions according to requirements of your software.
To create test cases in your live projects, you may require to reorganize your classes into packages and sub packages. For test cases, you may create new folder test/unittest in your project's main directory and then create test cases (scripts) according to packages and sub packages defined above.

#4 Guidelines and principles

Here are guidelines and principles of implementing unit testing to be followed by developer tram.

#4.1 How to write test cases 
  1. Best way to write test cases is to study an example given here and some more from PHPUnit documentation.
  2. 1st part of test script contains code to include necessary files/fixtures, while 2nd part contain test case class.
  3. In beginning develop simple tests for single method or collection of methods. After having certain experience, build more complex test cases. Finally go to suite level which provides fully automated testing environment.
  4. Create readable tests - write comments in Asserts and in UT. Write descriptive method names (even very long). Use local variables in Asserts. Use constants. UT should be readable like a book.
  5. Test cases must cover at least 75% of code. However this will be shown in reports generated by Phing when such tests are run from there. The danger of not implementing a unit test on every method is that the coverage may be incomplete. Just because we don't test every method explicitly doesn't mean that methods can get away with not being tested.
  6. You may require configuration parameters for database, paths and locations of other dependent software to run unit tests. For that there has been created a common file tests/unittests/config.inc.php which would be included in your test cases. Since it is common file or all tests, it is normally managed test/build manager. Hence if it is required to update that file, test manager must be consulted.
  7. Moreover this file should be included in your test cases as include_once or require_once constructs only otherwise there will be warnings/errors of duplication of code while running all tests together as suite from build system.
  8. If you find difficulties in creating/running tests cases for any of your class method etc., it means it requires regression that is to re-organize structure of class/class package to be able to test them in proper way.
  9. Since private methods of class can not be tested directly, it's corresponding public method should be tested. However every private method always has a parent public method which uses that private method. For more information visit Links sections.
  10. The concepts that you may need to be consider while building test cases (or suits) are Test-first programming, Code-coverage analysis, Refactoring, Incomplete tests, Agile documentation, Debugging Tests etc.
#4.2 How to organize and run them
  1. Developers should maintain hierarchy of classes as well as their equivalent test cases in same way. So for example if class file is grouped as Validate/Numeric.php then it's corresponding test case should also be grouped as Validate/NumericTest.php inside folder tests/unittests. Moreover name of test case class should also follow name of class that is to be tested. Same is true for phpDocumentator tags in test script. That is; tests scripts must be maintained as any other code- like Keep It Simple, Stupid (KISS)
  2. Fixtures (such as images, data files etc.) of test cases should be kept in same folder where test case/s reside/s. However for larger contents, they can be put in separate folder.
  3. All test cases are to be run from project's base directory only as shown in earlier example. This is necessary because it is required to generate agile documentation of unit tests cases and their classes.
#4.3 Testing instructions
  1. Test cases should not be designed in such a way that they require specific order of execution; that is they must run independent of other implementation.
  2. Test cases like to test Mail system, Database, File-system etc. requires additional setup apart from test script. Instructions about such setup and dependencies should clearly be mentioned in text file (like README.txt) inside corresponding test case's package. Such instructions can also contain information about how to run tests cases, other prerequisites, dependencies etc. wherever applicable.
  3. While overall instructions are to be kept at tests/unittests/README.txt file only.
#4.4 Scope of unit testing
  1. The crucial issue in constructing a unit test is scope. If the scope is too narrow, then the tests will be trivial and the objects might pass the tests, but there will be no design of their interactions.
  2. Likewise, if the scope is too broad, then there is a high chance that not every component of the new code will get tested. The programmer is then reduced to testing-by-poking-around, which is not an effective test strategy.
  3. It is recommended to write test cases for logical part only i.e static code/data need not to get tested. For complex test cases such as for Database, Mailing etc., it may require certain environmental settings. For that, concerned higher positioned person can be contacted for availability of it.
Bottom line of unit testing is that: it all depends upon the test case that you create. The better the cases, that covers all possible areas to be tested, the more worth the test is. If your test is poor, you wont yield advantages of unit testing.

#4.5 What tests should be written

While doing unit testing, it is important to know that what kind of tests should be done. There has been provided some insight about type of some tests.
  1. All positive test: This set of tests ensures that everything works as expected.
  2. All failure test: Use these tests on a one-by-one basis to ensure that every failure or exception case works.
  3. Positive sequence tests: This set of tests ensures that calls in the correct order work as expected.
  4. Negative sequence tests: This set of tests ensures that when calls are made out of order, they fail.
  5. Load tests: When appropriate, you can perform a small set of tests to determine that the performance of those tests is within an expected range. For example; 500 mails should be sent within 10-15 seconds.
  6. Resource tests: These tests ensure that the application program interface (API) properly allocates and frees resources-- for example, opening, writing, and closing a file-based API several times in a row to ensure that no files remain open.
  7. Callback tests: For APIs that have callback methods, these tests ensure that the code runs properly if callbacks are not defined. In addition, these tests ensure that the code runs properly when callbacks are defined but behave inappropriately or generate exceptions.
First 4 types of tests are must for every test-case. Rest can be implemented according to requirements in code.

#4.6 Unit testing in the context of team
  1. Developers should do unit testing of their developed libraries and dependent libraries only, i.e they don't require to do unit testing of whole library since other code might have other requirement/dependency about which they are not aware of. That means test-suite should be run by Test/Project/Development manager only.
  2. Above positioned persons can use build tools like phing to automate unit testing process, whenever there are changes in code, without manually running every time. Procedure of using Phing in unit testing and other tasks has been mentioned in this document.
  3. No untested code should be committed to version control, that is each package should have corresponding test cases.
#4.7 Re-usability of test cases/data
  1. Although it may seem like a good idea to throw random data at an interface, try to avoid it because the data is hard to debug. If data is generated randomly on each invocation, you may get an error on one pass that you don't get on another. If your test requires random data, generate the data in a file, then use that file on every run. In this way, you can have noisy data, but still be able to debug errors.
  2. In unit tests since each test case is tightly attached to particular piece of code, it is difficult to write re-usable test cases. However whenever possible, test cases/data should be made re-usable and hence should be kept in test library in order to re-use them for other projects.
  3. To create such library, Version control system can be used to store them in organized way under namespace like unit_test_library. And underneath that, there can be created several pages to describe nature of test case/data and how to use it in other projects. Similar practice can be used for functional test cases.

13 Mar 2008

Lighttpd vs. Apache

#1 Lighttpd overview

Lighttpd is an open source web server (similar like Apache) to server web pages. It has been developed by a MySQL developer named Jan Kneschke who developed this web server as a part of the C10K problem. Hence immediate reason of birth of Lighttpd is to overcome weakness, like reducing high memory footprint, of Apache web server.

The prefork model that Apache uses consumes a lot of memory (> 20 MB normally) per process. Which means if we multiply number of process to run simultaneously then RAM of server gets exhausted quickly. Lighttpd here beats Apache by using very low memory footprint (just 6MB) which means faster output from web server. The response appears even more faster when static contents are to be delivered. In Netcraft's latest web server survey, we can see Lighttpd among top 5 web servers currently used on Internet.

#2 How to set it up

Normal and most preferred installation instruction can be found from this installation page. For Yum users, a single command yum install zlib pcre lighttpd lighttpd-fastcgi will do almost all things.

If you want to start and stop Lighttpd manually, you're done. To install Lighttpd as a service like Apache, edit and install the init script (only if you have installed Lighttpd from source):

# sed -e 's/FOO/lighttpd/g' doc/rc.lighttpd > lighttpd.init
# chmod a+rx lighttpd.init
# cp lighttpd.init /etc/init.d/lighttpd
# cp -p doc/sysconfig.lighttpd /etc/sysconfig/lighttpd
# install -Dp ./doc/lighttpd.conf /etc/lighttpd/lighttpd.conf
# chkconfig lighttpd on

If you have installed Lighttpd using Yum then just follow last step. You may also use various other commands to start and stop Lighttpd web service like /etc/init.d/lighttpd start|stop|restart|condrestart|reload|status or service lighttpd start|stop|restart|condrestart|reload|status.

To just test lighttpd.conf, run command lighttpd -t -f /PATH/TO/CONF/lighttpd.conf

#3 Differences between Apache and Lighttpd

#3.1 General

The main difference between Apache and Lighttpd is the serving model, Lighttpd is event-driven and Apache is threaded or pre-forked.

Apache provides different multiprocessing models (MPMs) for different runtime environments. The prefork model that Apache uses creates number of processes at startup of service and manages them in a pool. However each process requires lot of memory to handle requests which means the more the processes the more memory will require. That is simultaneous apache processes quickly eat available RAM.

On the other hand Lighttpd uses single process, single thread and non-blocking I/O. For that it  uses fastest even handler in the target system like: poll, epoll, kqueue or /dev/poll. This difference makes Lighttpd faster than Apache in serving static files.

However the biggest difference between both is how they support scripting languages (specially like PHP). Apache has upper hand here because it supports easy to use Shared module version, CGI and FastCGI all together while Lighttpd supports only FastCGI at this  moment.

#3.2 Configuration level

There is visible difference between styles of configuration files of Lighttpd (lighttpd.conf) and Apache (httpd.conf). Syntax of lighttpd.conf will look more like syntax of php.ini while httpd.conf has XML type syntax. Here is an example of some basic configuration:

#3.2.1 Basic Configuration

Apache:

DocumentRoot /var/www/html
CustomLog /var/www/logs/access
ErrorLog /var/www/logs/error
User apache
Group apache

Lighttpd:

server.document-root="/var/www/html"
accesslog.filename="/var/www/logs/access"
server.errorlog="/var/www/logs/error"
server.username="apache"
server.groupname="apache"
server.modules=("mod_cml")

#3.2.2 Virtual Hosts

Below is an example of difference between VirtualHosts of Apache and Lighttpd. Example is shown for myproject project.

Apache:

NameVirtualHost *

<VirtualHost *:80>
 ServerName 'www.myproject.com'
 DocumentRoot '/web/
myproject/web'
 ErrorLog '/web/logs/
myproject_error'
</VirtualHost>

Include conf.d/virtualhosts/*.conf

Lighttpd:

$HTTP[“host”] == “www.myproject.com” {
 server.document-root=”/web/myproject/web”
 server.errorlog="/web/myproject_error"
}

#3.2.3 Authentication and Authorization

Lighttpd, at this moment, does not support .htaccess files, so all settings must be specified in the lighttpd.conf file, or the configuration files that it includes. However it understands Apache user files for basic and digest authentication, but group file support is not yet implemented but will be implemented soon. Here is an example of authentication and authorization:

Apache:

<Directory ~>
  AuthName "Authentication required to access this area."
  AuthType Basic
  AuthUserFile /web/myproject/docs/valid.users
  Order deny,allow
  Require valid-user
</Directory>
 
Lighttpd:

auth.backend="htpasswd"
auth.backend.htpasswd.userfile="/web/myproject/docs/valid.users"
auth.require=
("~" =>
  (
    "method" =>"basic",
    "realm"  =>"Authentication required to access this area.",
    "require"=>"valid-user"
  )
)

Summarily, configuration file of Lighttpd server behaves like an active script in which you can declare variables, write logic, do computation based upon criteria etc. similar like programming script. This feature makes configuration file alive and agile.

#4 How to run PHP under Lighttpd

#4.1 Configuring PHP under Lighttpd

Apache processes PHP internally i.e using it as Shared module mod_php while Lighttpd runs PHP under FastCGI. Although Apache also supports FastCGI, using PHP under FastCGI with Apache is neglected and is not used. However with Lighttpd, only option is to run under FastCGI, PHP must be compiled with FastCGI option (thought it is not used with Apache). For more information, please read http://trac.lighttpd.net/trac/wiki/TutorialLighttpdAndPHP. Below is the example of difference between running PHP under Apache and lighttpd.

Apache:

LoadModule php5_module modules/libphp5.so
AddType application/x-httpd-php .php

Lighttpd:

server.modules=( ..., "mod_fastcgi", ... )
fastcgi.server=( ".php" =>
                 (
                   (
                     "socket" => "/tmp/php-fastcgi.socket",
                     "bin-path" => "/usr/bin/php-cgi",
                     "broken-scriptfilename" => "enable",
                     "bin-environment" =>
                     (
                       "PHP_FCGI_CHILDREN" => "2",
                       "PHP_FCGI_MAX_REQUESTS" => "5000"
                     ),
                     "min-procs" => 1,
                     "max-procs" => 2,
                     "idle-timeout" => 60
                   )
                 )
               )

You may require to set path of php-cgi according to your setup. Please note that directive server.modules actually exists along with other modules on top of configuration file hence above line indicates that mod_fastcgi should be enabled in lighttpd.cnf.

Then it will require to set 1 directive in following way in php.ini configuration file if it exists, if  doesn't then nothing to do.

cgi.fix_pathinfo=1

Last 4 directives of above mentioned configuration are for running PHP scripts in better ways.

#4.2 Application wise changes

As FastCGI is a separate process, we can't handle directives of PHP into configuration file of web server (i.e lighttpd.conf). This is one of the biggest drawback of FastCGI that is why PHP is not used under FastCGI. Moreover under FastCGI mode, your PHP script would get limited support from web server which may force you to change or rewrite your scripts. Hence it is not recommended to use PHP under Lighttpd (at this moment because Lighttpd currently supports only FastCGI mode) because of it's lack of features that PHP will require like enabling configuration options of php.ini in configuration file for all hosts or per host base.

Moreover many benchmarks shows that PHP runs slower under FastCGI than under shared version on Apache.

However if it is required to run PHP on Lighttpd, then 2 major changes will require. They are:
  1. To move all PHP related setting either in php.ini directly or in configuration or global file of the application.
  2. Removing all Apache web server related variables and settings from application.
Once these changes are done, it will require to test application heavily to find whether functionalities of application get broken somewhere or not.

#5 mod_uploadprogress and Prototype

This feature will be available in Lighttpd version 1.5.0 which is not released yet, hence can not test or write more about it. More information about this module can be found at here. However when it will get released, it would surely be one of the finest module of Lighttpd server because it can be easily integrated with front-end applications using JSON.

#6 Lighttpd and output compression

Lighttpd provides output compression for static data through mod_compress module. Which means before sending static contents to client, mod_compress compresses it and saves at specified path. This compressed and cached copy will be served directly from cached location when similar request is made from same or different client. Thus saving valuable bandwidth and increasing response time.

Lighttpd supports 3 types of compressions viz. deflate, gzip and bzip2. The limitation of compressing and caching is that Lighttpd can not compress files with size more than 128 MByte and less than 128 Bytes.

To enable compression we need to set 3 directives in lighttpd.conf file. They are:

compress.cache-dir="/var/www/cache/myproject/"
compress.filetype=("text/plain", "text/html")
compress.max-filesize=1 MB

However since there is upper limit of file size of 128 Mbytes, the last directive is not necessary to declare. While compressing various types of static data, it should be kept in mind that if no file type or wrong file type is mentioned then no file will get compressed.

You may require to manually create cache folder and assign necessary write permissions to it. These cached contents do not automatically get cleared hence it is left to developer to clean it at periodic level when required. Following type of command can be used to remove contents that are older than a week.

$ find /var/www/cache/myproject/ -type f -mtime +7 | xargs -r rm

To compress dynamic contents, we need to reply on PHP itself as PHP natively supports good compression of dynamic contents. For that following 2 directives are to be set in php.ini or in equivalent configuration file.

zlib.output_compression=1
zlib.output_handler=On

Please note that to use zlib.output_compression, value of output_handler should be zlib.output_handler instead of standard output_handler. To do so, output_handler directive is to be set in following way:

output_handler=zlib.output_handler

or

zlib.output_handler=On

#7 Lighttpd and caching

#7.1 Caching overview

Caching is also another method to gain better performance in serving contents and increasing response time of your PHP scripts. There are several types of caching softwares available for PHP. Some important from them are Zend Platform, APC (APC GUI), XCache, eAccelerator, ionCube Encoder and PHP Accelerator. Certain web servers like Lighttpd provides built in modules for caching static contents at web server level. They are mod_expire, mod_mem_cache and mod_cml. Hence using combination of caching static and dynamic contents effectively, we can gain lot of speed in serving contents. However all of these mechanisms are not similar.

Aforementioned independent softwares are for Opcode/Bytecode caching i.e caching your PHP script into compiled state so that when new request arrives for same script, cache software will server compiled version of code directly from cache rather than reading file again from the disk and then compiling. From these 6, eAccelerator, XCache and APC are widely used caching softwares. This benchmarks also show that how XCache and APC are better than others. We will learn more about XCache in a short while.

As said earlier that only good combination of static and dynamic contents can give considerable boost in performance, we should try to cache as much contents as possible. To cache static contents, integrated modules of web server are the best candidates. In case of Lighttpd they are mod_expire and mod_mem_cache (however this is not provided as default).

#7.2 mod_expire

Mod_expire controls the Expire header in the Response Header of HTTP/1.0 messages. It is useful to set it for static files which should be cached like images, style-sheets etc. To use this module, first it needs to get enabled in server.modules directive array. Then module specific directives are to be set in server's configuration file as shown below.

<access|modification> <number> <years|months|days|hours|minutes|seconds>

Some examples could be like:
  • Cache contents of folder images for 2 hours.
expire.url = ( "/images/" => "access 2 hours" )
  • Cache contents of all sub-folders of images folder for 2 hours.
$HTTP["url"] =~ "^/images/" {
     expire.url = ( "" => "access 2 hours" )
}

Values can be hours, months, days etc. depending upon requirement.

#7.3 mod_mem_cache

Mod_mem_cache is a plugin which stores content of files in memory for faster serving. That is it stores specified file types into memory to serve directly from there without going to read it from disk from specified location thus saving disk read access time. This module is a 3rd party module, hence is not included in the official distribution of Lighttpd.

This module doesn't seem that much promising to use effectively for caching as memory should be used for processing data rather than storing data. Moreover memory should not be occupied for serving files that can reside and easily managed on disks. For example when we have thousands of images to be served then it is not advisable to store them into memory just to serve it faster. More information about this plugin can be found at here.

#7.4 mod_cml (Cache Meta Language)

Mod_cml is an another caching module similar like mod_expire which is provided by Lighttpd to cache static contents of dynamic pages. The difference between mod_expire and mod_cml is that mod_cml can cache fragmented static contents which are part of dynamic contents. For example a dynamic page called index.php might have static contents like menu.html, banner.html inside it which are not integral part of index.php. In such case using mod_cml, these 2 static contents can be cached and can be delivered directly from there.

But such type of caching can not be handled directly by Lighttpd web server and mod_cml hence we need to write some code in PHP or in special CML scripts for mod_cml which is written in lua programming language.

To use mod_cml, it requires to install lua programming language and libmemcache-1.3.x. Additionally Lighttpd must be compiled with 2 options --with-lua and –with-memcache.

#7.5 XCache

XCache is a newly emerging candidate in the market of caching PHP scripts. This is an independent software and not a module of Lighttpd. However it has been written by developers of Lighttpd.

XCache is an open-source opcode cacher, which means that it accelerates the performance of PHP on servers. It optimizes performance by removing the compilation time of PHP scripts by caching the compiled state of PHP scripts into the shm (RAM) and uses the compiled version straight from the RAM. This will increase the rate of page generation time by up to 5 times as it also optimizes many other aspects of php scripts and reduce server load. Some of the good features of XCache are:
  1. Optimized opcode cache.
  2. Using a generator to produce C code, reduces human mistake greatly.
  3. Running stable on PHP_4_3/PHP_4_4
  4. Supported and tested on all latest php cvs branches, such as PHP_4_3 PHP_4_4 PHP_5_0 PHP_5_1 PHP_5_2 HEAD (6.x)
  5. Alpha supported for in-alpha-php6, with Unicode enabled.
  6. Read-only Cacher Protection that prevents the cache from being corrupted by php-core/extension or any code other than XCache itself.
  7. Atomic get/set/inc/dec API operation on var cache for php programmers.
  8. Optimizer
  9. Encoder/Decoder(Loader)
  10. Administrator Script
  1. view statistics
  2. to see if it's AutoDisableOnCorrupted?
  3. view cached php/variable list
  4. clear cache
The last feature allows administrator to view statistic and cached PHP variables and manage caching behavior of XCache.

#7.5.1 Installing XCache

The standard way to install XCache is from source. Get your desired version of XCache from here. Then follow below steps to install it.

# tar -zxf xcache-*.tar.gz
# cd xcache
# phpize
# ./configure --enable-xcache
# make
# su
# make install
# cat xcache.ini >> /etc/php.ini

To make sure XCache is properly installed, run below command.

$ php-fcgi -v

It will show string like with XCache vX.X, Copyright (c) XXXX-XXXX, by XXX. Same can be checked from output of phpinfo() function also. Once XCache is installed, it will require to edit xcache.ini which contain various caching related directives to be used. However it is not mandatory to edit or change. A complete explanation of all the directives can be found from http://trac.lighttpd.net/xcache/wiki/PhpIni.

#7.5.2 Configuring Administrator panel

XCache Administrator panel is an important web interface that you can monitor and operate your opcode cache, seeing how well(or bad) it goes. Since this page is protected by http-auth, it will require to provide certain values in xcache.ini. For that set below 2 directives.

xcache.admin.user='USER'
xcache.admin.pass='MD5(PASSWORD)'

where USER is name of user you wish to use and MD5(PASSWORD) is MD5 encrypted string of password that you wish to use for given USER.

To set up web interface, copy xcache/admin/ (the whole directory) to your web document-root or sub-directory of it then request it from your browser, a http-auth prompt will popup where you will require to provide above USER and PASSWORD (as a normal string, not MD5 encrypted string). However sometimes installing XCache from rpm based utilities it may require to alias in web server instead of copying the script. To do so, add below directive in your server configuration file.

Apache:

Alias /xcache-admin/ /usr/share/xcache/admin/

Lighttpd:

alias.url += ("/xcache-admin/" => "/usr/share/xcache/admin/")

Gaining performance boost by using caching mechanism is tricky. Unless used carefully, it cannot give required boost. As we know that we can't cache everything (specially dynamic contents), we should try to cache whatever is left. This can be achieved by various types of caching as discussed above. Static contents are well cached by clients, if not then can be cached by web servers. PHP scripts can be cached using Opcode caching softwares like APC, XCache etc. While static part of dynamic data can be cached by modules like mod_cml (for lighttpd web server only).

#8 Summary

Summarily, Lighttpd web server is surely worth to have look at it and to be used for serving static data. For dynamic contents like PHP scripts, it is not optimized (because of support of only FastCGI) hence we have to wait until Shared module version PHP get started to support by it. At this moment it is widely used to server static contents only. So it will take time for it to really start competing with Apache.

However certain modules like mod_secdownload, mod_compress, mod_geoip, mod_trigger_b4_dl, mod_uploadprogress, mod_useronline etc. are peculiar modules of Lighttpd which can make it stand firmly with currently popular web servers.

#9 Links

http://www.onlamp.com/pub/a/onlamp/2007/04/05/the-lighttpd-web-server.html
http://survey.netcraft.com/Reports/0703/
http://schlitt.info/applications/blog/index.php?/archives/504-Apache-vs.-Lighttpd-echo-performance.html
http://trac.lighttpd.net/trac/wiki/TutorialInstallation
http://trac.lighttpd.net/trac/wiki/TutorialConfiguration
http://trac.lighttpd.net/trac/wiki/Docs:ConfigurationOptions
http://trac.lighttpd.net/trac/wiki/TutorialLighttpdAndPHP
http://trac.lighttpd.net/trac/wiki/Docs:ModUploadProgress
http://trac.lighttpd.net/trac/wiki/Docs:ModCompress
http://blog.lighttpd.net/articles/2006/08/01/mod_uploadprogress-is-back
http://trac.lighttpd.net/trac/wiki/Docs:ModCML
http://www-128.ibm.com/developerworks/library/os-php-fastapps1/index.html
http://trac.lighttpd.net/xcache/wiki/Faq