Blog

Performance benefits of using Prototypes in a nutshell

An often overlooked feature in the JavaScript world is Prototypes. Many developers are vaguely familiar with the concept and don’t understand the performance benefits of using Prototypes over adding functions to a constructor. Here is some code showing a Person constructor which we use to create object instances based off of the constructor with different properties.

function Person(name, age, job){
   this.name = name;
   this.age = age;
   this.job = job;
   this.outputUser = function(){
       console.log(this.name + ' is ' + this.age ' years old and is a ' + this.job);
   }
}
var josh = new Person("josh", 21, "frontend developer");
josh.outputUser();
//outputs: josh is 21 years old and is a frontend developer

The code above may seem perfectly fine but this causes are outputUser method to be duplicated every time we create a new object which takes up a lot of memory and slows down runtime. A better way of doing this is to create a prototype method which will be inherited on instances instead of duplicating the methods/properties on every instance of the object. Accessing a method from the object will be faster with the above method since JavaScript will look through the scope chain first for the method/property and if it doesn’t find it then it looks at the prototype chain but less memory will be used and creation of objects will be much faster using Prototypes. Here is an example of the code above using Prototypes.

function Person(name, age, job){
   this.name = name;
   this.age = age;
   this.job = job;
}
Person.prototype = {
    constructor: Person,
    outputUser: function(){
       console.log(this.name + ' is ' + this.age ' years old and is a ' + this.job);
    },
    changeJob: function(job){
       this.job = job || "no job";
       return console.log(this.name + " has changed is job to " + this.job);
    }
};

The code above uses an object literal to create prototype methods which is a much more performance efficient way of creating methods/properties that you will need across multiple instances. This is much more better for the following reasons.

  • We now have encapsulation of our methods and can easily view our needed properties/methods
  • We aren’t duplicating our methods every creation of a new object but are inheriting them
  • It gives a flexibility in the long run to change method/properties on the fly and we don’t have to worry about if an object created at an earlier time has the new method/property we added later on

One disadvantage since we are overwriting the prototype with a new object literal is that the constructor property no longer points to the prototype. This is why we set it manually using constructor: Person

Here is a JSPerf benchmark test comparing Closure, Prototype, Static, and The Revealing Module Pattern. The Closure and Prototype methods are close speed wise but Prototypes are faster when you are generating a lot of objects where Closures are faster when you’re using a lot of methods or accessing properties often. The Closure method is slower when you have a lot of objects created at runtime which have duplicated methods taking up more memory making them take longer to create.
http://jsperf.com/closure-prototype-static-performance/19

Hopefully this helps a few people and if anyone notices anything incorrect or has any questions feel free to leave a comment below. Thanks!

Setting up a Require.js and Backbone.js project quickly with Bower

The Setup

I’m normally always looking for ways to speed up development and reduce recursive mundane tasks such as starting a project or setting up boilerplate code. I recently came across Bower which is a package management tool created by the developers at Twitter. Bower depends on Node and NPM and is installed globally by running the following command

npm install -g bower

Once you have Bower installed you then can install packages and dependencies using these commands

# Using a local or remote package
bower install <package>
# Using a specific version of a package
bower install <package>#<version>

You can also create a bower.json file which is what I prefer and it allows you to define the packages needed along with dependencies and then simply run bower install to download packages

bower.json

{
	"name": "RequireJS Starter",
	"version": "1.0.0",
	"dependencies": {
          //the value is the version you want,
         // if you enter null it grabs the latest release
		"jquery": "1.9",
		"backbone": null,
		"underscore": null,
		"requirejs": null
	}
}

By default if we were to do an install right now it would create a bowser-components directory and download all the packages inside the directory. I like to have my packages download into js/libs you can achieve this by creating a .bowerrc file

.bowerrc

{
	"directory": "js/libs"
}

Now after creating that file inside the app directory you can run the following command, you should see all of your packages in the js/libs folder after

bower install

Loading Require.js

Now that we have all of our packages needed for the app we can create our index.html file and include require.js

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title>Requirejs with Backbone example</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width">
        <!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
        <link rel="stylesheet" href="css/main.css">
        <script data-main="js/main" src="js/libs/requirejs/require.js"></script>
    </head>
    <body>
        <!--[if lt IE 7]>
            <p class="chromeframe">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">activate Google Chrome Frame</a> to improve your experience.</p>
        <![endif]-->
        <!-- Add your site or application content here -->
        <p>Hello world! This is HTML5 Boilerplate.</p>
    </body>
</html>

Typically you would load scripts at the end of the body but since require.js is AMD and loads scripts in a non-blocking asynchronous nature we load it at the top. After loading the require.js library we establish our configuration and initialization file by adding a data attribute to our script tag data-main and then entering the path to our main.js file minus the extension. This loads our main.js asynchronously which then configures our various libraries/dependencies and initializes our app.

Configuring dependencies and packages for Require.js

We’re now going to create a main.js file in our js directory.

//the require library is configuring paths
require.config({
	paths: {
                //tries to load jQuery from Google's CDN first and falls back
                //to load locally
		"jquery": ["http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min",
					"libs/jquery/jquery"],
		"underscore": "libs/underscore/underscore-min",
		"backbone": "libs/backbone/backbone-min"
	},
	shim: {
		"backbone": {
                        //loads dependencies first
			deps: ["jquery", "underscore"],
                        //custom export name, this would be lowercase otherwise
			exports: "Backbone"
		}
	},
        //how long the it tries to load a script before giving up, the default is 7
	waitSeconds: 10
});
//requiring the scripts in the first argument and then passing the library namespaces into a callback
//you should be able to console log all of the callback arguments
require(['jquery', 'underscore', 'backbone', 'app'], function(jquery, _, Backbone, App){
	new App;
});

We have to configure the script paths first. For jQuery we try to load it from Google’s CDN and if it doesn’t connect we fallback to a local version of jQuery. Shim allows you to Configure the dependencies, exports, and custom initialization for older, traditional “browser globals” scripts that do not use define() to declare the dependencies and set a module value. We let Backbone know it needs jQuery and Underscore to load and set the export to Backbone.

Returning data from a View

Now we’re going to create a base Backbone View and return some data to make sure it’s all connected and the scripts are loading in the correct order. We define the Backbone module and then create a view. Inside the view we add a initialize method which returns a console.log. After that we return the View.

define(["backbone"], function(Backbone){
	var App = Backbone.View.extend({
		initialize: function(){
			console.log("it's working!");
		}
	});
	return App;
});

Now you should be able to load it in your browser and see “it’s working!” and see no errors in the console. If you come across any problems or errors comment below.

Building a responsive grid with CSS3 flexbox and no floats or clearfix!

In this tutorial I’m going to show you how to get started and get comfortable with using the CSS3 flexbox property. Flexbox is a layout mode provided for the arrangement of elements on a page which behave predictably when the page layout must accommodate for different screen sizes and display devices. Flexbox also does not use floats (pretty amazing eh?) and nor do the flex container’s margins collapse with the margin of it’s content. This allows for complex layouts and layouts containing many child elements to be much more lightweight and easier to code ( no need for extra jank and ugly clearflxes ). So lets get started!

We’re first going to build out the bones of the site and start with the HTML ( If you’ve used Grid Frameworks before this should look familiar )

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title>Responsive Flexbox Grid</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width">
    </head>
    <body>
		<header>Responsive Flexbox Grid</header>
		<div class="wrapper">
		  <div class="row">
		    <div class="col-1"></div>
		    <div class="col-11"></div>
		  </div>
		  <div class="row">
		    <div class="col-2"></div>
		    <div class="col-10"></div>
		  </div>
		  <div class="row">
		    <div class="col-3"></div>
		    <div class="col-9"></div>
		  </div>
		  <div class="row">
		    <div class="col-4"></div>
		    <div class="col-8"></div>
		  </div>
		  <div class="row">
		    <div class="col-5"></div>
		    <div class="col-7"></div>
		  </div>
		  <div class="row">
		    <div class="col-6"></div>
		    <div class="col-6"></div>
		  </div>
		  <div class="row">
		    <div class="col-7"></div>
		    <div class="col-5"></div>
		  </div>
		  <div class="row">
		    <div class="col-8"></div>
		    <div class="col-4"></div>
		  </div>
		  <div class="row">
		    <div class="col-9"></div>
		    <div class="col-3"></div>
		  </div>
		  <div class="row">
		    <div class="col-10"></div>
		    <div class="col-2"></div>
		  </div>
		  <div class="row">
		    <div class="col-11"></div>
		    <div class="col-1"></div>
		  </div>
		  <div class="row">
		    <div class="col-1"></div>
		  </div>
		  <div class="row">
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		  </div>
		  <div class="row">
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		  </div>
		  <div class="row">
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		  </div>
		  <div class="row">
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		  </div>
		  <div class="row">
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		  </div>
		  <div class="row">
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		  </div>
		  <div class="row">
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		  </div>
		  <div class="row">
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		  </div>
		  <div class="row">
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		  </div>
		  <div class="row">
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		  </div>
		  <div class="row">
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		    <div class="col-1"></div>
		  </div>
		</div>
    </body>
</html>

As you can probably see the layout is a 12-col grid layout. What this means if you’re not familiar with CSS grid frameworks is that each row can amount to 12 columns together. So for example you have one row and inside that row you can put any combinations of columns ( 6 + 6 = 12 OR 3 + 6 + 3 = 12 ). Typically with CSS Grid Frameworks if you go over the parent column size the layout breaks into a new row but when using Flexbox is just dynamically adjusts the columns to fit the parent container.

Example: Sidebar Layout

		<div class="wrapper">
		  <div class="row">
		    <div class="col-3">
		    	<div class="row">
		    		<h1>heading test</h1>
		    	</div>
		    	<div class="row">
			    	<div class="col-1">test</div>
			    	<div class="col-1">test</div>
			    	<div class="col-1">test</div>
		    	</div>
		    	<div class="row">
		    		<div class="col-1">test</div>
		    		<div class="col-1">test</div>
		    		<div class="col-1">test</div>
		    		<div class="col-1">test</div>
		    		<div class="col-1">test</div>
		    		<div class="col-1">test</div>
		    		<div class="col-1">test</div>
		    	</div>
		    </div>
		    <div class="col-9">
		    	<h1>Main Heading</h1>
		    	<div class="main col-9">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloribus, pariatur, dicta consequatur error fugit eligendi optio rerum laboriosam natus cum non a iure hic neque esse mollitia similique earum corporis.</div>
		    	<div class="col-9">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Excepturi, aut, tempore nostrum quis doloribus reiciendis deleniti sed nesciunt dolor consequatur veniam veritatis eligendi quam corporis ducimus aliquam dolore explicabo adipisci.</div>
		    </div>
		  </div>
		</div>

Now that we’ve covered the structure we’re going to go over the presentation/styling. I used SASS/Compass in the original project and download files but for this tutorial i’m going to explain it using plain CSS so people that don’t have SASS & Compass setup can still go through the examples. With that being said you’re probably going to want to include some sort of CSS reset or CSS normalize to standardize your layout across browsers. Now lets get started on making the columns work, thanks to Flexbox we’re going to only need to add some pseudo selector magic along with media queries and we’re good to go.

header{
	height:100px;
	font:Verdana;
	text-align:center;
	color:#FFF;
	background:#0bf;
}
.wrapper{
        /* this is going to have multiple media queries attached adjusting the max-width to the device screen size */
        /* in SASS I can add them right here like so which i think is much more understandable and readable */
        /*
	@media all and (min-width: 768px){
		max-width:720px;
	}
	@media all and (min-width: 1024px){
		max-width:980px;
	}*/
	margin:30px auto;
}
/* next important piece is this CSS pseudo selector */
/* it's an attribute wildcard selector that finds all classes that match "col-" */
/* similar to [class^=] which searches for "begins with.." and [class$=] which searches for "ends with..." */
[class*="col-"]{
	margin-bottom:2%;
	min-height:30px;
	border:1px solid rgba(0,0,0, .08);
	background:rgba(0,0,0,.08);
}
/* Now we add the flexbox magic inside of our media query */
/* For each incremented column we add box-flex/flex with the incremented value along with the supported vendor prefixes */
@media all and (min-width: 768px){
	.row{
		display: -webkit-box;
		display: -moz-box; /* OLD: safari, ios, android */
		display:-ms-flexbox; /* MID: IE 10 */
		display:-webkit-flex; /* NEW: chrome 21+ */
		display:flex; /* NEW Firefox 22+, Opera 12.2 */
		width:100%; /* OLD: Firefox (bugfix) */
	}
	[class*="col-"]{
		margin-right:2%;
	}
        [class*="col-"]:last-child{
                margin-right:0;
        }
	.col-1{
		-webkit-box-flex: 1;
		-moz-box-flex:1;
		-ms-flex:1;
		-webkit-flex:1;
		flex:1;
	}
	.col-2{
		-webkit-box-flex: 2;
		-moz-box-flex:2;
		-ms-flex:2;
		-webkit-flex:2;
		flex:2;
	}
	.col-3{
		-webkit-box-flex: 3;
		-moz-box-flex:3;
		-ms-flex:3;
		-webkit-flex:3;
		flex:3;
	}
	.col-4{
		-webkit-box-flex: 4;
		-moz-box-flex:4;
		-ms-flex:4;
		-webkit-flex:4;
		flex:4;
	}
	.col-5{
		-webkit-box-flex: 5;
		-moz-box-flex:5;
		-ms-flex:5;
		-webkit-flex:5;
		flex:5;
	}
	.col-6{
		-webkit-box-flex: 6;
		-moz-box-flex:6;
		-ms-flex:6;
		-webkit-flex:6;
		flex:6;
	}
	.col-7{
		-webkit-box-flex: 7;
		-moz-box-flex:7;
		-ms-flex:7;
		-webkit-flex:7;
		flex:7;
	}
	.col-8{
		-webkit-box-flex: 8;
		-moz-box-flex:8;
		-ms-flex:8;
		-webkit-flex:8;
		flex:8;
	}
	.col-9{
		-webkit-box-flex: 9;
		-moz-box-flex:9;
		-ms-flex:9;
		-webkit-flex:9;
		flex:9;
	}
	.col-10{
		-webkit-box-flex: 10;
		-moz-box-flex:10;
		-ms-flex:10;
		-webkit-flex:10;
		flex:10;
	}
	.col-11{
		-webkit-box-flex: 11;
		-moz-box-flex:11;
		-ms-flex:11;
		-webkit-flex:11;
		flex:11;
	}
	.col-12{
		-webkit-box-flex: 12;
		-moz-box-flex:12;
		-ms-flex:12;
		-webkit-flex:12;
		flex:12;
	}
}

and that’s it! wah lah now you have a responsive grid system using no floats or clearfix. It’s nice not needing as much code right? Hopefully after playing around with the examples a little bit you realize how awesome flexbox truly is.

Support:
http://caniuse.com/flexbox

Download source:
COMING SOON!
NOTE: uses SASS and Compass

Make CSS3 gradients work in all browsers

In this brief tutorial I’m going to go through providing support for CSS3 gradients. The gradient CSS property has been around for a while now but it didn’t support IE7 – IE9 until as of recently. You can now use SVG Data-URIs which are Base64 encoded URLs that simply render something on the page whether its a small gradient or a cat. This is awesome because it saves you a extra HTTP Request and it gets cached along with your CSS files. Here is the code to make it happen

			background: #1e5799; /* Old browsers */
			/* IE9 SVG, needs conditional override of 'filter' to 'none' */
			background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzFlNTc5OSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iIzI5ODlkOCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjUxJSIgc3RvcC1jb2xvcj0iIzIwN2NjYSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiM3ZGI5ZTgiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
			background: -moz-linear-gradient(top, #1e5799 0%, #2989d8 50%, #207cca 51%, #7db9e8 100%); /* FF3.6+ */
			background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#1e5799), color-stop(50%,#2989d8), color-stop(51%,#207cca), color-stop(100%,#7db9e8)); /* Chrome,Safari4+ */
			background: -webkit-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* Chrome10+,Safari5.1+ */
			background: -o-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* Opera 11.10+ */
			background: -ms-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* IE10+ */
			background: linear-gradient(to bottom, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* W3C */
			filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#1e5799', endColorstr='#7db9e8',GradientType=0 ); /* IE6-8 */

PHP load balancing and connecting to slaves to read your data

So now you have a successful website that is starting to generate more traffic and receive more requests for data. If you’re only using one central web server this will only be viable for so long. A solution is to start using Load Balancing which is one of the first steps to scaling your website for higher traffic. It requires having multiple web servers which handle the traffic or multiple requests being received. The general concept is to have a central point or master server where all the requests arrive and then handling the various requests off to various web servers or slaves. You can usually use Software Balancers in the beginning to get you by without having to pay for multiple web servers. Software Balancers offer features like output caching, GZIP compression, and more. The popular Software balancers include reverse proxy mode so you can enable load balancing. These Software Balancers are apache,Nginx, and Squid. Now back to the idea of the Master slave setup you will have one server that acts as the master, the true repository of the data. You then setup another MySQL server configuring it as the slave of the master. All actions take place on the master and are replayed on the slave. Anytime you need to change data on the server ( update, delete, and insert ) you command the master. For read access you connect to the slave instead. As you can imagine their is some slave lag that happens, the data on the master may be newer than the data on the slave because of multiple updates being processed and typically with PHP when we insert data we want to grab it back after inserting. ex:

$master->exec('update users set posts += 1');
$results = $slave->query('select posts from users');

A solution for this is to count the number of posts before the data is inserted and then compare the number of posts after inserting the data to see if the data has been inserted. Another solution is to have multiple MySQL slaves attached to one web server or even better have a load balancer that has a multiple web servers connected and they each have their own slave connected. Now the problem is knowing which slave to connect to. The solution is to sever the relationship between Web Servers and MySQL database slaves by randomizing the connections between them. This can also help with availability allowing a slave to go down and your application not care, it will just pick another slave instead and read from it. Here is some sample PHP code on getting this working.

<?php
class DB{
	//configuration info
	private static $user = 'testuser';
	private static $pass = 'testpass';
	private static $config = array(
		'write' =>
			array('mysql:dbname=MyDb;host=10.1.2.3'),
		'read' =>
			array('mysql:dbname=MyDb;host=10.1.2.7',
				  'mysql:dbname=MyDb;host=10.1.2.8',
				  'mysql:dbname=MyDb;host=10.1.2.9')
		);
	//static method to return database connection
	//if it has a problem finding one slave database it connects to another
	//to retrieve the data
	public static function getConnection($server){
		//First make a copy of the server array so we can modify it
		$servers = self::$config[$server];
		$connection = false;
		//keep trying to make a connection
		while(!$connection && count($servers)){
			//this can be changed to find which server is closest to the client
			//and sends a heartbeat back the fastest
			$key = array_rand($servers);
			try {
				$connection = new PDO($servers[$key], self::$user, self::$pass);
			} catch (PDOException $e) {}
			if(!$connection){
				//we couldn't connect. remove the server
				unset($servers[$key]);
			}
		}
		//if we never connected to any database, throw an exception:
		if(!$connection){
			throw new Exception("Failed: {$server} database");
		}
		//otherwise....
		return $connection;
	}
}
//do work
$read = DB::getConnection('read');
$write = DB::getConnection('write');;
//commenting code saves lives
?>

Hopefully this helps you understand a little more about scaling your application to support more users by using load balancing.