Keeping an eye out for a better recording, but considering this happened just 30 mins ago — it’s the best I could do ( Drew Kerrigan actually recorded it on his iPhone here at work, good job Drew ). Without further ado, Lockerz CEO, Kathy Savitt, on CNBC Power Lunch! Congrats Kathy!
Chris Page – Software Engineer
… and student of Life, Philosophy, and Learning
A CTO recently made a comment that some oddly high % of people above a particular salary range play N amount of video games a week. I thought it was interesting, as I couldn’t disprove it, ha! So, in effort to keep this page a little active, and not having the time to write out a well-thought-out technical tutorial, I decided to write about something fun, a video game I got into this week: Storm8’s World War ( picture on the left ). It’s a dice-based massively multi-player phone game for both Android and iPhone.
How it works?:
You pick your faction ( one of 5 global super powers ), each with their own benefits. You then complete missions, earn money, buy bigger and badder units, and compete with other players.
What’s fun about it?:
One thing I particularly enjoy about World War is that it’s simply addictive – there are few controls and few options, so I don’t really need to deeply involve myself in the game to have fun with it. I play here and there. I like this, because I’m so very busy these days – I haven’t really had time to join my buddies in the Starcraft 2 train, and I can only play my Wii in small dosages. So phone games that I can carry around and play here and there is quite fulfilling.
Tips?:
I’ve only been playing for about a week, but like many other multi-player phone games, World War continues while you are offline. So, it’s probably a good tip to build a lot of defense, so that other players don’t loot your cash flow while you’re gone! When it comes to attacking, the best thing you can do is have a couple friends join your alliance. The bigger your alliance, the more effective your attacks and defenses are. Ie, if you are in an alliance of 4 people, you typically almost always win against an enemey from an alliance of 2 ( though not always, just usually ).
Join my alliance!:
If anybody wants to join the game, post your alliance code in the comments or shoot me an email — I’ll invite you to my alliance!
Enjoy,
In addition to moving my servers to save costs, I ran into a two part issue that I lumped into: “I need to tune memory usage a bit”.
Part 1: Apache
Since I moved my Apache servers to lower memory instances, I was running into swap space usage that I could easily avoid, ie:
free -m
total used free shared buffers cached
Mem: 268 245 22 0 71 53
-/+ buffers/cache: 120 147
Swap: 511 29 482
Some of the reasoning behind this was that, by default, Apache expects a bit more memory to be available than what I provided to it in the move. The fix was to introduce a few settings to lower child processes and limit concurrent connections to something more reasonable to the type of traffic my site really gets – which is near nothing most days.
The settings I dropped into apache were:
httpd.conf:
#Low Memory Settings
StartServers 1
MinSpareServers 4
MaxSpareServers 2
ServerLimit 6
MaxClients 6
MaxRequestsPerChild 3000
I made the adjustments, cleared out the swap space with:
swapoff -a swapon -a
Then restarted apache:
/etc/init.d/apache2 stop /etc/init.d/apache2 start
And all was well in the world.
free -m
total used free shared buffers cached
Mem: 268 207 60 0 31 79
-/+ buffers/cache: 97 170
Swap: 511 0 511
Part 2-1: PHP
A bit simpler, my blog site was running into max memory allocation limits. I had left the default php.ini in place in the upgrade, so I needed to do a once over of configs and change memory_limit from 16M to something more reasonable for my site.
php.ini
memory_limit = 64M ; Maximum amount of memory a script may consume (16MB)
Part 2-2: APC
Having Apache settings set for lower memory usage also allowed me more room to increase my APC cache limit a bit higher to keep more pages faster. From 30 MB to 50 MB.
apc.ini
extension=apc.so apc.enabled=1 apc.shm_size=50
Other obvious solutions in consideration, switch to Rackspace to invert my memory/cpu requirement/cost ratios. Any other tips are welcome
So, recently I decided I was paying too much for my server because I was not maximizing performance across all the various daemons. So I decided to split my larger server into a handful of smaller servers to be able to fine tune each one to dedicated purposes. All went well, but I had some trouble for a few evenings figuring out how I could port forward localhost:3306 to the, now remote, database server. This should have been dirt simple with an iptables rule – but after digging in, I discovered MySQL treats localhost “special” by sending connections through the unix socket file, which is absolutely faster, but only works if the database daemon is on the same host as the connecting application.
After doing some research, I found it is possible to use a tool like socat and autossh to wrap an ssh tunnel to forward connections through the socket file to a remote IP over TCP. This however, was more complex and one off than I cared to explore for my simple problem. I finally resorted to using DNS and to stop using localhost as the host name. However, a few tid bits for the weary traveler:
- The mysql client library is responsible for selecting the protocol.
- PHP’s internal mysql libraries, unfortunately, as far as I could discover ( please correct me if I am wrong here ), do not allow you to select the protocol.
- So if you’re using “localhost” as your host name in a PHP mysql_connect, you’re forced to go through the socket file, however, you can use 127.0.0.1 instead of localhost to force TCP.
- The linux mysql-client package command line tool offers a –protocol=tcp flag if you want to force TCP. You can also set this as a default inside /etc/mysql/my.cnf under the [client] heading
my.cnf:
[client] port = 3306 socket = /var/run/mysqld/mysqld.sock protocol = TCP
Again, this appears to work fine if you’re not using PHP as your client.
I hope this lesson learned ( use DNS ) comes as a helping hand to others out there. If anybody has some other suggestions, please do leave a comment!
I’ve been knee deep in performance and scalability for some time now, and have used and learned of many useful tools and techniques to help out. One of my favorite command line tools for seeing how well a single Apache server is churning out pages in development comes stock on Ubuntu, and Mac OS X: Apache Benchmark.
A simple performance test against the homepage of one of my client site’s using AB at the command line:
ab -t5 -n100 http://www.teamgzfs.com/
The results:
This is ApacheBench, Version 2.3 <$Revision: 655654 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking www.teamgzfs.com (be patient) Finished 664 requests Server Software: Apache/2.2.8 Server Hostname: www.teamgzfs.com Server Port: 80 Document Path: / Document Length: 306 bytes Concurrency Level: 100 Time taken for tests: 5.054 seconds Complete requests: 664 Failed requests: 0 Write errors: 0 Total transferred: 465003 bytes HTML transferred: 205326 bytes Requests per second: 131.38 [#/sec] (mean) Time per request: 761.143 [ms] (mean) Time per request: 7.611 [ms] (mean, across all concurrent requests) Transfer rate: 89.85 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 38 78 48.7 64 994 Processing: 114 540 226.2 493 1690 Waiting: 114 531 205.6 493 1485 Total: 191 618 236.0 558 1808 Percentage of the requests served within a certain time (ms) 50% 558 66% 587 75% 598 80% 617 90% 845 95% 1163 98% 1402 99% 1746 100% 1808 (longest request)
There is quite a bit of useful information here that can help you tune your code and server. It’s important to note however, that when working on a larger site, that expects quite a bit more traffic, you might want to investigate some more thorough solutions outside of just a single machine and ab. It is, however, a nice starting point into useful information.
One rather funny pitfall you can run into however, is if the host you are sending requests to is smartly secured – these types of tests become a bit useless, as they may have security settings to limit or delay requests – providing you with timeouts and/or inaccurate information. Best to run these types of things in a semi-developmental mode with those types of security settings turned down, and rely on bigger guns or fleets of boxes and scripts to hit a production secure site.
In addition to hitting just a landing page, you can use AB to send COOKIE or POST data too! This is very useful if you want to see how pages perform but need credentials to get in first. This is a little trickier to do using the -c, -T, -p, and -v flags. I noticed there are under-useful resources online to figuring it out with AB, so it would seem worthwhile to write it – as it took me some trickery to figuring it out as well:
Sending POST data to a login form:
First we create a file that contains our URL encoded post data. Note, AB expects the values to be URL encoded, but not the equal (=) or ampersands (&).
post_data.txt
username=foo%40bar.com&password=foobar
Capturing a cookie:
Here, we use the verbosity (-v) flag so we can see the response headers that come back — many sites will send back a cookie once authenticated, we’ll want to capture that cookie here. Though, some sites will not require it, I demonstrate it for the sake of example:
ab -v4 -n1 -T 'application/x-www-form-urlencoded' -p post_data.txt http://www.foobar.com/login
The returned response header will fly by quick, you’re looking for something like the following:
Set-cookie somesession=somerandomsessiondata...;
The session data may come back encrypted, unencrypted, a serialization, or just a number. That varies by site. The point here is you have a key/value pair for the cookie. All you need is the part up to the semi-colon ( not including the semi-colon ). Copy that “key=val” string, and use it when hitting other pages on the site you are testing, ie:
Using a cookie to test a page that requires a cookie:
ab -t10 -n100 -c 'somessession=somerandomsessiondata' http://www.foobar.com/login_required_page
This can become a lot of fun once you get the hang of it. Now you have the know how, go enjoy creating an arsenal of these scripts and start performance tuning your sites – or script hacking your favorite social network ( or obnoxious Blizzard clan website hahaha… drum roll for D3 – 2010? Please???! ).
Two weeks down, this blog is due for an update – time has been flying!
As far as home life in Pittsburgh goes – ROCK. I’m currently staying roughly between one of Carnegie Mellon and Pittsburgh University’s campus intersections – the architecture is gorgeous. I enjoyed a meal at the famous Primanti Brothers down the street, learned the public transit ( a work in progress… ), and discovered a few open mic hot spots I’ll be hitting up eventually – oh, and Lil Wayne at the Post Gazette Pavilion was also ROCK! I’ve had numerous other experiences and visited quite a few restaurants, but won’t detail all my eating habits here
As far as Lockerz goes… ROCK ON! I’ve made some new friends, thoroughly enjoyed many philosophical discussions, and am getting knee deep into working on the next best thing. Today was a moment for Lockerz history – as we saw an incredible traffic increase this morning – ranking 4 on Google Trends around 10 a.m.
The boost seemed grass roots in nature, as people are catching wind and telling their friends, who are telling their friends. The most personable for me was Amber’s friend made a comment about needing a Lockerz invite to join the site, not even realizing I work there. Small world? Needless to say, he got the invite.
I won’t detail much else about the job – you’ll have to keep tabs on the site! Need an invite? Let me know.
I’ve been quite busy lately! Amber and I decided to leave Morgantown, WV to pursue better opportunities wherever we may fall. We bunked up with family for a few weeks… a grueling thing with a 2 month old. Thankfully, it didn’t take too long to stumble upon the next big thing! Spending so much time increasing my online presence has paid off – as I received a call a few weeks ago from Lockerz CTO, Peter Meulbroek.
Peter and I exchanged a few phone calls – I could tell there was something “right” about the vibe I gained. Three weeks later I drove into Pittsburgh for a lengthy yet fun and relaxing 5 stage interview – their idea is spectacular and the team was very talented and cool with a work hard and play harder mentality, perfect. I realized “I’m going to make this happen”. Thankfully the team at Lockerz shared that realization, and I’m very proud to announce that as of July 27th 2009, I will begin my first day as a ground floor Lockerz technical team member!
This proves it… I’m a startup junkie!
Things are moving very quickly, with only a week to relocate, and it reminds me of one of Amber’s favorite sayings: “Good things take time, Great things happen all at once.” – this seems to hold true for me, a man of extremes to say the least!
Everybody involved in the process made it feel absolutely “right”. I’m super psyched about the challenging workload ahead, and Amber and I both have never been so happy with the direction life is taking us!
Go check out Lockerz.com!
( I’m publishing this partially done so that it acts as a reminder for me to FINISH it… bare with me! )
Overview of Important Changes
variable class naming
Previously in PHP, only method and function names could be variables. Ie:
$func = "print";
$func("Hello World");
class Foo {
public static function Bar()
{
echo "Hello World";
}
}
$method = "Bar";
Foo::$method();
Now, in PHP 5.3+, variable class naming is also supported – making possible this syntax:
class Foo {
public static function Bar()
{
echo "Hello World";
}
}
$class = "Foo";
$method = "Bar";
$class::$method
This new class variable naming should provide a much desired level of ambiguity for PHP developers, I know for my MVC framework, it could really change the Typhoon PHP Typhoon->run() method in a positive way.
late static binding
This is a more advance PHP OOP topic – that almost came off as a bug in previous versions of PHP. I’ve personally ran into it myself on occasion, and am happy to see a solution available in PHP 5.3. In previous versions of PHP, static calls resolved to the inherited class. In cases where one needed a static call to resolve in it’s own scope, unexpected results were common. Ie:
class Foo {
public static function who() {
echo __CLASS__;
}
public static function test() {
self::who();
}
}
class Bar extends Foo {
public static function who() {
echo __CLASS__;
}
}
Bar::test();
Output:
Foo
The solution, “Late Static Bindings”, solves this using the static keyword:
class Foo {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who();
}
}
class Bar extends Foo {
public static function who() {
echo __CLASS__;
}
}
Bar::test();
The static keyword resolves to the calling class and produces the expected output:
Bar
Additions to Standard PHP Library (SPL)
Circular Garbage Collection
Lambda Functions (Anonymous Functions)
Closures
Overriding Internal Functions
New Reserved Words
Namespaces
Jump Labels
Changes to Functions and Methods
Extensions
Phar
php.ini Changes
Deprecated Methods
Install php 5.3 on Ubuntu
mkdir download && cd download wget http://snaps.php.net/php5.3-200906131830.tar.gz
My wife and I found a baby sitter to watch our daughter, Gabriella, tonight, and we were able to enjoy a Saturday night out, finally! Upon our return home, our sitter and good friend notified us that at midnight June 14th EST, Facebook opened up username based URL’s – or to us tech savvy people, vanity URLs or permalinks. Facebook did already have permalinks to user profiles, but they were difficult to remember and non-arbitrary.
While many major companies were able to acquire their “facebook/mycompany” URL ahead of public release, I know many will be in competition to get theirs ASAP. Our sitter quickly rushed home to be ready to snatch up his – I was unfortunate to still be stuck using my middle initial:
With as many software people named Chris Page – I didn’t expect for it to be easy…but what really chaps me, is a dancer in Australia got to it first! WTF? Amber was equally disappointed in the commonness of our last name, when she too had to use her middle initial:
You can register your vanity URL at facebook.com/username.
Ubuntu + Compiz
2009
This is actually from awhile ago ( almost a year ), but I thought I’d share. It’s my desktop pc, running Ubuntu 8.04 and Compiz Fusion engine.
To be honest, it was a fun exploration for the novelty, but these days, the most I really use from the effects engine is the magnifier to help people standing over my shoulder focus on whatever I’m demonstrating.
Pretty cool none the less! Read up at Compiz Fusion and Ubuntu





Digg
Disqus
Facebook
Flickr
LinkedIn
MySpace
oDesk Profile
Twitter
YouTube!
Comment