Archive

Archive for the ‘PHP’ Category

My 2013 Goals to Learn New Technologies

September 30th, 2013 1 comment

That’s right, I’m setting goals for 2013 on the last day of the third quarter. But my current status warrants the urgency. I have been a PHP developer since I started at The Nerdery exactly 6 years ago this month. Within the first few months I learned Zend Framework (version 1.0.2 at the time). I have developed all of my projects since then in Zend Framework. In doing that I have come to be somewhat of a Zend Framework expert.

In addition to being involved in over 400 projects I have also taken on more of a management role as a Principal Software Engineer (PSE). I am now leading a team of 7 other PSEs. Our team is in charge of recruiting, mentoring developers, helping with sales and resourcing needs, and defining and enforcing standards, among other things. Doing all of these non-development things, along with my focus on Zend Framework 1, has caused me to miss 6 years of changes in web development.

Now with Zend Framework 1.x being sunsetted in 2014 and Zend Framework 2 being released, which at first blush feels very foreign to me, I find myself at a cross-road. I can either continue to float further and further away from actual programming and focus on management and project leadership, or dive back in and reintroduce myself to the new stuff.

Without further ado, here’s my list of technologies that I want to learn by the end of 2013:

  • Groovy on Grails
  • OpenStack, or other virtualization environments
  • Vagrant + Puppet/Chef
  • Varnish
  • Javascript MVC (Backbone, RequireJS, Underscore, Grunt)
  • MongoDB
  • Solr
  • Symfony2
  • Node.js
  • .Net MVC

Hmm, that’s a pretty long list. I probably won’t get to all of them by the end of the year. But if I can stay focused I will hopefully be able to reap the benefits by being more effective at my job and assuring my long-term career opportunities in the industry. I hope my friends and colleagues can hold me to it and help me achieve this goal.

Categories: Personal, Zend Framework Tags:

Zend_Config Benchmark – JSON, Array, INI, XML, YAML

March 6th, 2012 9 comments

Zend Framework supports reading and writing from configuration files of 5 different types (JSON, Serialized Array, INI, XML, and YAML).

It is most common to see INI used for application config files. But config files can be used for many different uses including navigation, translations, or ACLs.

If you application relies on parsing one or several config files each time it is bootstrapped it is important that you select a file format that is fast to parse. But you also want to select a config file format that is easy for a human to read and edit.

In a recent application I am building I also had the need to write modifications to config files, so I also benchmarked the Zend_Config_Writer components.

First I started with a relatively small config INI config file and parsed this to a Zend_Config object. I used this Zend_Config object for benchmarking the writers. Then I used the writen config files for benchmarking the readers.

Following is the source config file:

<pre>includePaths.library = APPLICATION_PATH "/../library"
appnamespace = "Application"
autoloaderNamespaces[] = Bar_
autoloaderNamespaces[] = Foo_

; PHP Settings
phpSettings.display_startup_errors = 0
phpSettings.display_errors         = 0
phpSettings.error_reporting        = 2147483647
phpSettings.log_errors             = 1
phpSettings.error_log              = APPLICATION_PATH "/../data/logs/phperrors.log"

; Bootstrap
bootstrap.path  = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"

; Locale
resources.locale.default = "en_US"
resources.locale.force = true

; Front Controller
resources.frontController.controllerDirectory.default                    = APPLICATION_PATH "/controllers"
resources.frontController.actionHelperPaths.Bar_Controller_Action_Helper = "Bar/Controller/Action/Helper"
resources.frontController.actionHelperPaths.Foo_Controller_Action_Helper = "Foo/Controller/Action/Helper"

; View
resources.view.encoding = "UTF-8"
resources.view.doctype  = XHTML1_TRANSITIONAL
resources.view.helperPath.Bar_View_Helper_ = "Bar/View/Helper/"
resources.view.helperPath.Foo_View_Helper_ = "Foo/View/Helper/"
resources.view.strictVars = on

; Layout
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"

; Mail
resources.mail.transport.type       = smtp
resources.mail.transport.host       = "localhost"
resources.mail.defaultFrom.email    = no-reply@example.com 
resources.mail.defaultFrom.name     = "Example"
resources.mail.defaultReplyTo.email = no-reply@example.com
resources.mail.defaultReplyTo.name  = "Example"

; Application Log
resources.log.stream.writerName          = "Stream"
resources.log.stream.writerParams.stream = APPLICATION_PATH "/../data/logs/application.log"
resources.log.stream.writerParams.mode   = "a"
resources.log.firebug.writerName         = "Firebug"

resources.db.adapter                 = "pdo_mysql"
resources.db.params.host             =
resources.db.params.username         =
resources.db.params.password         =
resources.db.params.dbname           =
resources.db.params.profiler.enabled = true
resources.db.params.profiler.class   = "Zend_Db_Profiler_Firebug"</pre>

Following is the script for running the benchmark. Thanks to Gregory Drake Wilson for getting me started on this benchmark script.

<pre>&lt;?php

// Setup Zend Framework Autoloader and Bootstrap Application
include '_common.php';

$iterations = 1000;
$config = new Zend_Config($application-&gt;getOptions());

/**
 * Writes
 */

$start = microtime(true);
for ($i = 0; $i &lt; $iterations; $i++) {
	$iniWriter = new Zend_Config_Writer_Ini(array('config' =&gt; $config, 'filename' =&gt; 'data.ini'));
	$iniWriter-&gt;write();
}
echo "INI Write   - $iterations - " . (microtime(true)-$start) . "s\n";

$start = microtime(true);
for ($i = 0; $i &lt; $iterations; $i++) {
	$jsonWriter = new Zend_Config_Writer_Json(array('config' =&gt; $config, 'filename' =&gt; 'data.json'));
	$jsonWriter-&gt;write();
}
echo "JSON Write  - $iterations - " . (microtime(true)-$start) . "s\n";

$start = microtime(true);
for ($i = 0; $i &lt; $iterations; $i++) {
	$xmlWriter = new Zend_Config_Writer_Xml(array('config' =&gt; $config, 'filename' =&gt; 'data.xml'));
	$xmlWriter-&gt;write();
}
echo "XML Write   - $iterations - " . (microtime(true)-$start) . "s\n";

$start = microtime(true);
for ($i = 0; $i &lt; $iterations; $i++) {
	$yamlWriter = new Zend_Config_Writer_Yaml(array('config' =&gt; $config, 'filename' =&gt; 'data.yaml'));
	$yamlWriter-&gt;write();
}
echo "YAML Write  - $iterations - " . (microtime(true)-$start) . "s\n";

$start = microtime(true);
for ($i = 0; $i &lt; $iterations; $i++) {
	$arrayWriter = new Zend_Config_Writer_Array(array('config' =&gt; $config, 'filename' =&gt; 'data.array'));
	$arrayWriter-&gt;write();
}
echo "Array Write - $iterations - " . (microtime(true)-$start) . "s\n";

/**
 * Reads
 */

$start = microtime(true);
for ($i = 0; $i &lt; $iterations; $i++) {
	$configData = new Zend_Config_Ini('data.ini');
	clearstatcache('data.ini');
}
echo "Ini Read    - $iterations - " . (microtime(true)-$start) . "s\n";


$start = microtime(true);
for ($i = 0; $i &lt; $iterations; $i++) {
    $configData = new Zend_Config(include 'data.array');
	clearstatcache('data.array');
}
echo "Array to Zend_Config Read  - $iterations - " . (microtime(true)-$start) . "s\n";

$start = microtime(true);
for ($i = 0; $i &lt; $iterations; $i++) {
    $configData = include 'data.array';
	clearstatcache('data.array');
}
echo "Array to Array Read  - $iterations - " . (microtime(true)-$start) . "s\n";

$start = microtime(true);
for ($i = 0; $i &lt; $iterations; $i++) {
	$configData = new Zend_Config_Json('data.json');
	clearstatcache('data.json');
}
echo "JSON Read   - $iterations - " . (microtime(true)-$start) . "s\n";

$start = microtime(true);
for ($i = 0; $i &lt; $iterations; $i++) {
    $configData = new Zend_Config_Xml('data.xml');
	clearstatcache('data.xml');
}
echo "XML Read    - $iterations - " . (microtime(true)-$start) . "s\n";

$start = microtime(true);
for ($i = 0; $i &lt; $iterations; $i++) {
    $configData = new Zend_Config_Yaml('data.yaml');
	clearstatcache('data.yaml');
}
echo "YAML Read   - $iterations - " . (microtime(true)-$start) . "s\n";</pre>

Server Details:

  • Debian Linux 6.0
  • PHP 5.3.9
  • json support enabled
  • 4 cores
  • 8GB RAM

My findings:

Test Runs Time (s) Runs/s
INI Write 1000 3.94 254
JSON Write 1000 1.28 781
XML Write 1000 3.17 315
YAML Write 1000 1.97 508
Array Write 1000 1.56 641
INI Read 1000 2.70 370
Array Read 1000 0.53 1887
Array to Zend_Config Read 1000 1.14 877
JSON Read 1000 9.82 102
XML Read 1000 3.06 327
YAML Read 1000 261.29 4

My initial reactions was, what the hell is wrong with YAML reading. I read through the source of Zend_Config_Yaml and saw up to 3 calls to preg_replace() for each line of YAML, which doesn’t necessarily indicate that it is flawed. As a follow-up to this post I intend to figure out exactly where the Yaml parser is getting held up. Until I am able to do this, I have discounted YAML entirely.

Of the two formats that are human readable/editable (INI and XML), XML is 20% faster to write and INI is 12.5% faster to read.

Of the non-human-editable formats (Array and JSON), Array wins hands down for reading and is 134% faster than it’s closest contender (INI), but JSON is the fastest for writing (20% faster than Array). The reason Array is so much faster for reading is that the process is entirely native to PHP (you just have include the file and assign it’s response to a variable). Because of this, there is no Zend_Config_Array for reading.

Update:

Thanks to @Balbuzar I noticed that my initial test of unserializing the Array did not return a Zend_Config object (but rather just an array), so I’ve added “Array to Zend_Config Read” above and it is still the fastest of all of the Zend_Config read options, and is 57% faster than INI reading.

Conclusions:

If you need a human-editable config format that is primarily for reads, then INI is your best bet.

If you need speed and can sacrifice human-readability, then Array is the clear winner.

 

Categories: PHP, Zend Framework Tags: ,

PHP Session Locks – How to Prevent Blocking Requests

December 17th, 2010 47 comments

Many people are aware that modern browsers limit the number of concurrent connections to a specific domain to between 4 or 6. This means that if your web page loads dozens of asset files (js, images, css) from the same domain they will be queued up to not exceed this limit. This same problem can happen, but even worse, when your page needs to make several requests to PHP scripts that use sessions.

Read more…

Categories: PHP Tags: , , ,