A quick recap of what I have done(HHVM included), what I have learned from this experience and where I am going from here.
- Post I - Show the code for what is compared. Initial results.
- Post II - Updates with Composer and results of tests.
Over what seems like several months now (in reality it has probably only been a few weeks), I wrote a very simple blog for myself. Originally, I started the project with Phalcon, which at that time was at version 1.2.7. I had played with Phalcon before, as far back as v0.5.0, but this time I really wanted to dig into it and get to know it better. So I did and when ready to publish it to my newly provisioned tier over on OpenShift, I found that the bash script I used to provision Nginx was not working properly and did not correctly parse the environment variables as it should have. So I had to tear down the whole thing, yeah I just about cried, and start over a new. But now, for some unknown reason, Phalcon would not build on the service. I had put a good bit of time into writing a script that would do this (actually, I had to learn how to write this as I went) and now... nothing seemed to be working properly. As a test, I copied the Phalcon project out to a folder on my desktop and replaced it with a newly installed version of Laravel. After a quick 'git push' to the service, I was up and away.
At this point, I was so frustrated, but I had no choice and I proceeded to rewrite the blog in Laravel. I had spent a month or more learning about writing Bash scripts and the internal workings of servers and for what? To end up writing a blog on something that I already knew. The whole point of this, in case you're wondering, was to learn new things. Really put pressure on myself to push through some really hard tasks. Well, I did... but I still feel like I failed in some ways. And believe it or not, I'm ready to give it a go again! But for now, I am here, so I will shake the flag pole a few times first before traversing the mountain again.
Writing the Project with Phalcon
Starting out, I really did not know what to expect. After displaying a few static pages, getting used to having to include the keyword "Action" on my controller methods and not having to maintain a routes.php file, I sorta got the hang of things. But then things started getting weird when I first played with "Volt", which is the built-in template engine that comes in Phalcon. It's, let's just say, not "Blade". I don't know why I thought it would be. Ignorance really. Blade is Blade, right. So why would i think that Volt would be a perverse copy of Blade. Once I got that through my thick skull, I spent a few hours sorting out my layouts and partials, and everything sorta feel into place. It became very intuitive and I really like it!
My Gracious - Migrations
Next (since I was ready to get going with the data portion of the program), as with any good Laravel work-flow, was migrations. Right? Not so fast Charlie Brown! As I quickly found out, no! Which just made me sit there and stare blankly at my laptop for a solid minute or so. I mean, migrations are in there, but not like you would think. They work, for the lack of a better term, backwards to what you might be used to in a Laravel workflow. Basically, in Phalcon: you create your database, your tables, you create your project, you create your models from those tables, yada yada yada. When you're happy with how everything is set-up, you run the migration on your database. This produces, basically, a MySQL dump of the database that you can then import into your production database. Umm... Ok... Well, it works and it's different, so... moving on.
Composer and Autoloading
In the project, I used Parsedown to parse all the markdown that I pull from the database and display on the post pages. Also, I used Jeremy Kendalls Password Validater for, you guessed it, password validation. Yeah, Phalcon has a Security class that contains a password hash check method, but i wanted to use this instead. Well, Phalcon is not loaded through Composer. Wait! I think I just heard someone fall out of their chair. Yep, I did! But yeah, since Phalcon is written as an extension to PHP, you do not start off your project with a composer.json file and download Phalcon into the root of your project directory. Yep, there goes someone else. You can still use Composer and all of it's goodness though so everyone get back in your chairs.
At first, all I did was use Composer to bring the libraries into my project. I then manually added them to the loader.php file, found in /app/loader.php of my Phalcon project. And that worked. But I later learned that I could've just adjusted my composer.json file and tell it where to put my files it downloads. Phalcon already loads up a "Library" folder, just for this purpose. Still, worked like a champ and I did not have to worry about maintaining two separate arrays for loading up the two packages. Oh, yeah. The reason I had to do that was because Jeremy's package was properly namespaced, but Parsedown is not. And that makes sense, since it is really only one file. So I had to have a namespace array and a classmap array. Ok! So why was I doing that? Doesn't Composer do all that for you? Yeah, it will. But it wanted to put Parsedown into the namespace class. Which worked fine, if I left everything the way Composer wanted it (leave all packages in the vendor folder, in the root of the project, and added a require statement to the autoload.php file within index.php), this caused a big performance hit. That is until I was reminded, by Maks Surguy of a little command option of Composers called --optimize. This takes all your Composer packages and creates a single class map, which is far and away more performant. In Laravel, it shaved 200ms off the average response times for each page load. 200ms is huge! In the Phalcon project, not running the command and adding the require statement added 30+ function call to each request and over 100ms to response times. Thats huge too, but horrible! After running the optimize command option, it shaved the 100ms off the average times again, which I was happy with.
At the end of the day, I personally don't care how many functions are being called. It's the response times that those functions invoke that I care about.
Phalcon does not have a built-in authentication mechanism like Laravel does. Given that PHP versions 5 >= 5.5.0 have really nice built-in password hashing functions and given that I am running on v5.5.8, I could've just as easily used those in some simple "if' statements. But that's lame, so I took this as an opportunity to write my own authentication class. It actually turned out pretty nice (it worked!). This is where Jeremy's Password Validater library came in. I want to rewrite it has a separate library, which will allow me to reuse it in other projects. It will have to be framework agnostic and able to work across different versions of PHP. Even those environments that are running v5.3. This library does that and it's awesome. I will be posting what will hopefully be a really nice post on the subject in the coming weeks.
Overall Phalcon Site Performance
The Phalcon sites average response time to load the index page is : 74 ms. This runs a query to retrieve all the posts from the database, display them on the index page and parse the markdown. Oh Happy Days! Bear in mind, that response time is the measure of time from when the request is sent to the server and the server responds with data..
Rewriting the Project with Laravel
I knew that rewriting the project in Laravel would not be bad. Mostly because I am already fairly familiar with it. I have done one other decent sized project with it, so... I was comfortable. I knew the syntax. I knew the docs. Hell, if I didn't know what method or class to use for something, most of the time, I could guess it. Most of the time!
Laravel's API is great like that, once you get comfortable with it's syntax. I compare it to being in a dark room that you are familiar with.You can walk around and you might bump into things, but you're probably not going to break anything.
But, I guess it's fair to say that everyone, when using a new framework for the first time, is a bit like a bull in a china shop.
What took me a week to maybe a week and a half to write in Phalcon (because I was getting used to it and learning the docs too) I was able to rewrite in Laravel over the course of a weekend. The only real sticking point I had during the rewrite was "Form Model Binding". Some things had changed a bit, I think, from version 4 to version 4.1 and I just could not get my head wrapped around it. Also, for the life of me, I could not look-up a post by it's name. I fought this and fought this, but finally just relegated myself to look-ups based on ID's. This really sucked! Hence the reason my URI looks like, "domain.com/posts/3". Really, it's a stupid little thing! Why? Because I did the same thing in the previous project and it worked perfectly. But in v4.1, the find() method was type-hinted to "int" Looking into this just now, I think I see what the problem might be. Another post coming to address this, so... Moving on... Nothing to see here people!
Overall Laravel Site Performance
The Laravel sites average response times started out at a, first reported 2050 ms+. I soon found that I had some issues with the hard drive in my laptop. Response times varied greatly! I replaced my drive with a WD Black drive, and things seemed to level out quite a bit. Although the Phalcon site was still running at around 74ms, the Laravel site was now reliably running at around 680ms. HOLY CRAP! That's a big performance gap! Running the command mentioned earlier, "php artisan optimize"(which is just a alias to the composer native command "composer dump-autoload --optimize"), shaved an extra 200 ms. That brings the project down to an average request time down to 480 ms. Which is not bad. We are just below half a second between sending a request to our server and getting a response back.
HHVM to the Rescue... Maybe!
Since replacing my hard drive, I decided that I would finally force myself to get away from WAMP and pick up the Vagrant flag and wave it around a bit. Well, to say that it has kicked my backside would be putting it lightly. But, I did get a recent version of HHVM v3.0.1 running on an Nginx server with 512mb ram. And just how did this affect response times? Believe it or not, it shaved a very respectable 50% off the response times. That puts the sites average response time down to 240ms. Could there be more that could be squeezed out of this. I'm sure there is, but this is even with Gzip as well, so I don't know. Then again, I am no server guru.
Where from Here?
What did I take away from all of this? Well, I am still very firm believer in using the right tool for the job. But honestly though, I cannot see any type of project that Phalcon would not be great at. Although I was using it as a full MVC stack, you can just as easily instantiate it as a micro framework and use routing to put together a rock solid, fast as hell, API. I personally don't think that another framework is going to come along anytime soon that is going to perform any better than Phalcon. But, with that said, if you are just so against learning a new framework or cannot get past the fact that Phalcon is a fairly young/immature framework that you want to stick with what you are doing now, then you have got to look into HHVM and get familiar with it. If not, you are going to get left behind. Seriously! I personally feel that within the next few years, there are going to be enough projects lost by PHP developers to Nodejs developers( Wal-Mart/Node Video, ChangeLog Episode with Eran Hammer ), that PHP devs are going to have to make the shift one way or the other. If not Phalcon or making the switch to Node for certain project. At the very least switch to HHVM.
Why would I say such a thing?
Sites are expensive! E-commerce sites that get a lot of traffic are very expensive! Social network/intranet CMS sites are even more expensive. Clients, at some point, are going to want to cut costs. Their only options are not building their sites as they really need them, or they are going to have to save a ton on their recurring costs. Hardware, scaling costs, hosting are those costs. By using projects like Phalcon or HHVM, will allow you to place heavy traffic or process intensive sites on smaller hardware that scales less than it does today. Imagine if you could tell a possible new client that your shop can cut their hardware/scaling costs in half! What do you think their response will be when you show them that you can.