Posted on

PHP Switch Vs If Performance

When writing a complex application such as Store Locator Plus, you will often find multiple logic branches to handle a given task.   There are two oft-used methods for processing the logic; the If-Else construct and a Switch statement.    Since I am always looking to optimize the Store Locator Plus codebase for performance, some sites do have hundreds-of-thousands of locations after all, it was time to look into the performance-versus-readability of those two options.

The general consensus, though I’ve not taken the time to run performance tests with the WordPress stack myself, is that “you should use whatever makes your code easier to read are more easily maintained”.  For me that means using switch statements.    I find the construct much easier to extend and not cause inadvertent side effects.  Something I’ve learned in 20-plus years of working on code teams and in long-run projects like Store Locator Plus.

On the pure performance standpoint an if-else can be marginally faster if performing less than 5 logic comparisons.

PHP If Else Statement
PHP If Else Statement

Switch statements will often be faster at-or-near 5 logic comparisons as code optimization within C, and likely carried forth in the PHP psuedo-compiler, will often turn the 5+ logic branches of a switch statement into a hash table.  Hash tables tend to be faster with all branches of the code having equal access time.    Statistically speaking a large number of iterations will favor the equal access time model over the “first-fastest” model of an If-Else.

PHP Switch Statement
PHP Switch Statement

Possibly faster and always easier-to-extend and read, Switch will be my “weapon of choice” whenever I have more than  a simple 2-state if/else logic branch to be tested.

Posted on

Recreating Kickstarter Is Not A $3500 Project

“It is simple, really. It is exactly like Google, but better. We are going to have an extra button on the search page.”

We hear it every week. Some business guy has the next greatest thing since sliced bread. It is exactly like some other application, web services, or mobile app but better. OK, we get that. There are hundreds of ways to build a better mouse trap. But this is what kills us…

“My budget is $500 and I need it done next week”.   

Yes, this happens ALL OF THE TIME. How often? Well, here are some real world examples from TODAY alone:

  • Migrate my old website to WordPress (a good start). The old site is on a proprietary MySQL database (OK, no big deal). I need a new look, user interface, and a modern design (still with you). There are 12,000 products and pages that need to be converted (wow, that is a BIG project!).
    My budget is… less than $500
  • We want to create a crowdfunding website (cool, there is still room in this market). We want it to have ALL of the features built into Kickstarter (wow, that is ambitious) and add these 10 must-have features that make us better (wow, you really need pros like us, this is going to be a year-long project).
    My budget is $3500 – $4500.

The Simple Black Box

The problem is that most people just don’t understand the “black box” that they sit in front of every day. They type something on the keyboard or touch the icon on their iPad and stuff magically happens. It is simple. Thus the assumption is that the stuff to make the simple happen must also be simple.

Sadly people think that just because someone else has created a website or application already that it will be cheap and easy to make an exact replica with ZERO ACCESS to any of the behind-the-scenes code or technologies involved. What people don’t realize is there are thousands of man-hours and often hundreds-of-thousands of dollars involved in making the most popular sites & services easy-to-use. Or maybe they do realize that, but they think that coming up with the idea is the hard part.

Ideas Are Easy

Ideas are easy. Everyone you know has come up with an idea. How to make something great. The mistake too many people make when it comes to creating a better website or application is assuming that the people they are emulating overlooked the low-lying fruit. They immediately see a gold-mine opportunity because their favorite application or service is missing a feature they deem “the awesome factor”.

Some idea people are business people. MOST idea people are not. A true business person will evaluate their own concepts and truly understand the market. Who are they competing with? Why hasn’t the competition done this yet? What are the real costs involved in creating the concept?

Do Your Homework

When it comes to applications and web services, MOST people have no clue about that last part. What are the real costs involved? Many things are overlooked. The costs of graphic design. The costs of hosting a server that can handle 12,000 visitors/day. The costs of keeping the security and load-balancing updated for a high traffic site. Writing the code. TESTING the code. Refactoring and re-designing the system.

To get an idea about how much these things costs, you need to DO YOUR HOMEWORK. Spend at least 10x as long as you did finding a development partner, programmer, or CTO  to pitch your idea to and do some research. Who else is doing something similar? How long did they spend developing and refining their service?  What did they spend on it? Surprisingly, for many semi-successful companies this information is available online; if not disclosed directly then via some very accurate estimates by industry watchers.

Keep Your Common Sense

When you suddenly have a flash of inspiration on how you are going to retire a billionaire in a year, don’t drop common sense on the floor and go out the door naked yelling “Eureka!”. Sadly, common sense is often the first thing that is left behind at this moment. Do you really think that nobody else came up with your idea? If so, do you really think you can develop an application that is going to generate $1,000,000 in sales by October and do it in 3 weeks for $5,000? If it was THAT easy every one of your neighbors would be a millionaire. Even the most brilliant business and technology people out there, Bill Gates and Steve Jobs included, did not create a million-dollar app in a month.

So please, do all of the contract programmers in the world a favor. Stop, evaluate, investigate, and most of all just have some common sense before you click send on that email request asking us to recreate the next Kickstarter, Google, or Facebook in a week for $500.

Posted on

WordPress Activation Hook

WordPress Development

We recently discovered an issue in our commercial plugins related to a change in the WordPress API. It turns out that since WordPress 3.1 was released the register_activation_hook() function is no longer called during a plugin upgrade! This is a significant change in behavior from previous versions that called the WordPress activation hook on every update.   This has caused numerous problems and forced Cyber Sprocket to come up with a patch in our own wpCSL framework.

Why Is This A Problem?

Any site running a version of WordPress older than 3.1 would automatically get any feature  and supporting application tweaks whenever they upgraded the plugin.   Most plugin authors, Cyber Sprocket included, would use the register_activation_hook API call to make sure the user had the latest database structure, settings, and other elements that keep the plugin working.    For example, with Store Locator Plus 3.0 this hook would ensure that the user’s Google Maps API v2.0 settings were converted to the Google Maps API v3.0 equivalent.

As of WordPress 3.1 the function that does this conversion is not called.    To make matters worse, it is not called only in certain circumstances.  For example:

  • User installs upgrade via a downloaded zip file: updates called.
  • User does auto-update on a deactivated plugin then activates the plugin: updates called.
  • User does auto-update on an activated plugin: updates NOT called.

As you can see this is inconsistent.  Even worse, plugins that worked find up to version 3.1 now have the potential to suddenly break.

The Solution?

Cyber Sprocket has created a new version of our wpCSL framework that we use to build WordPress plugins.   The update uses standard admin panel interfaces to call our own “plugin has changed” hooks.    The short version of how this works is as follows:

  • User is on the admin panel…
  • The plugin is active…
  • Check the version of the plugin as stored in the options table of WordPress…
  • Is it different than the current version of our plugin?
    • Yes, run the upgrade callback function if it is set.
    • Update the plugin version stored in the options table to the current installed version.

That’s it.  A fairly simple solution, but more things we need to manage in our plugin framework because the WordPress development team changed things.

 

Posted on

PHP Puts the Un in Unset

Recently I have seen—both in our code and that of others—the use of unset() in PHP as a means of reclaiming memory. I do not think this a good practice, and in my opinion we should not consider it part of our toolbox. Mainly because I worry it gives a false sense of aid, when in reality unset() rarely has any impact.

PHP is not a language that gives you fine-grained control over memory.

You do not have control over when variables are freed from memory, and you cannot force PHP to release memory. You can give hints to PHP, and unset() is such a hint, but that is it. If you are relying on unset() to help your memory problems, it is indictative that you already have a larger problem, which unset() is not going to solve.

I have seen unset() used in these ways most often:

function foo() {
    $bar = array(...);
    $baz = some_function();

    // Lots of work here

    unset($bar);
    unset($baz);
}

function blah( $bar, $baz ) {
    // Code code code
    unset($bar);
    unset($baz);
}

In both cases the calls to unset() can be omitted with no change in memory usage. Profiling will demonstrate this, and you can easily write a quick script using memory_get_usage() to see the lack of difference for yourself. When you call unset() you are telling PHP that it is alright to free that variable. However, this is already the case for variables which go out of scope. In both functions above the $bar and $baz variables are no longer in scope at the functions’ end, and PHP flags them for garbage collection. Calling unset() here is redundant.

Note that this is not true when references are involved.

function foo( &$bar ) {
    // Do a bunch of stuff
    unset($bar); // No effect
}

Calling unset() on a reference _will not_ mark that variable for garbage collection because unset() cannot affect variables beyond the scope of its call point (with one exception). PHP will ignore the call to unset() above. Because $bar is a reference, it was not pushed onto the stack as a function argument, and there is not a temporary, lexically scoped $bar inside this function for PHP to reclaim – making this unset() a no-op.

This is true of globals unless you access them via $_GLOBAL, which is the above mentioned exception.

function foo() {
    global $bar;
    unset($bar); // No-op
}

function foo() {
    unset($_GLOBAL['bar']); // Has intended effect
}

Semantically, unsetting a variable is on par with assigning it a null value. Assigning a null is ever so slightly faster, but can take up ever so slightly more memory; PHP maintains a reference count in memory on variables with null value, but unset() variables have their reference count removed immediately. Speed versus space trade-off, but I’m not sure of a situation where it would ever be meaningful.

PHP even lets you cast things to ‘unset’. I have never seen anyone do so, and I cannot imagine a reason for ever doing so. It has the same effect as casting to null. Interestingly, it is _not_ the same as calling unset() on a variable. This can be seen by observing how casting to ‘unset’ will not remove a variable from the symbol table.

function foo($x) {
    var_dump( get_defined_vars() );
}

function bar($x) {
    unset($x);
    var_dump( get_defined_vars() );
}

foo( (unset) 'Lobby' );
bar( 'Jones' );

The above will print out
array(1) {
["x"]=>
NULL
}
array(0) {
}

The cast has no effect on the $x created within the scope of foo().
Curiously the cast has no effect within its own scope either.

$foo = 'Lobby';
bar( (unset) $foo );
echo $foo;

The above will echo ‘Lobby’, as the cast does not unset $foo within the current scope. Or within the scope of the function call, as seen above. In this context ‘unset’ is a synonym for ‘null’. This fact can be stressed by pointing out that the cast is possible in places where unset() as an expression is a fatal error.

foo( (unset) 10 ); // Works. Same as foo(null)
unset( 10 ); // Fatal syntax error.

You cannot unset() literal values, but you can cast them as unset just fine. Good ol’ quirky PHP.