PHP vs Javascript – Performance test

We are going to do a performance test on getting the data from MySQL database using PHP vs getting data from MySQL database using AJAX in Javascript. We have a database named classicmodels and a table named orderDetails.

In both the cases, we are fetching data from MySQL database with the help of PHP. But in 1st case, we load the data directly via PHP. And in 2nd case, we load the data via AJAX. It is basically loading the data PHP vs Javascript.

Following is a code that will get the data from database using PHP:

<table>
    <tr>
	    <th>Order number</th>
	    <th>Product code</th>
	    <th>Quantity ordered</th>
	    <th>Price each</th>
	    <th>Order line number</th>
    </tr>
 
    <?php
        $conn = mysqli_connect("localhost:8889", "root", "root", "classicmodels") or die(mysqli_connect_error());
    
        $sql = "SELECT * FROM orderdetails";
        $result = mysqli_query($conn, $sql);

        $data = array();
        while ($row = mysqli_fetch_object($result))
        {
            ?>

            <tr>
                <td><?php echo $row->orderNumber; ?></td>
                <td><?php echo $row->productCode; ?></td>
                <td><?php echo $row->quantityOrdered; ?></td>
                <td><?php echo $row->priceEach; ?></td>
                <td><?php echo $row->orderLineNumber; ?></td>
            </tr>

            <?php
        }
    ?>
</table>

We have created a table with 5 columns. Then we are making a connection with the MySQL database. Then we are getting all the data from orderDetails table. We are using a while loop to loop through all records and mysqli_fetch_object function will return the next row in each iteration. When we use PHP to get data from the database, we get the following results in performance:

performance test php
performance test php

Now we use the same database, same table, the same number of records, and the same output. In order to get the data using Javascript, we need to create an HTML tag for the table. No need to run any PHP query, not even connection with the database. Give a unique ID to the tag where you want to display all data, in this case, we want to show the data in the table so we have given an ID to tbody tag. Then we are sending an AJAX (no jQuery needed) to test.php file and when the response is received from that file, then we display that data in tbody tag. The response sent from test.php is JSON string so we have to decode that using Javascript JSON.parse function.

index.php

<table>
    <tr>
	    <th>Order number</th>
	    <th>Product code</th>
	    <th>Quantity ordered</th>
	    <th>Price each</th>
	    <th>Order line number</th>
    </tr>
 
    <tbody id="data"></tbody>
</table>
 
<script>
    var ajax = new XMLHttpRequest();
    ajax.open("POST", "test.php", true);
    ajax.send();
 
    ajax.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {

        	console.log(this.responseText);
            var data = JSON.parse(this.responseText);
            console.log(data);
 
            var html = "";
            for(var a = 0; a < data.length; a++) {
                html += "<tr>";
                    html += "<td>" + data[a].orderNumber + "</td>";
                    html += "<td>" + data[a].productCode + "</td>";
                    html += "<td>" + data[a].quantityOrdered + "</td>";
                    html += "<td>" + data[a].priceEach + "</td>";
                    html += "<td>" + data[a].orderLineNumber + "</td>";
                html += "</tr>";
            }
            document.getElementById("data").innerHTML += html;
        }
    };
</script>

Now we need to create a file that will handle that AJAX request. This code will be almost same as we did in simple PHP, but instead of displaying all data, we are adding all data in an array and sending that array as a JSON string to AJAX response using PHP built-in json_encode() function.

test.php

<?php

	$conn = mysqli_connect("localhost:8889", "root", "root", "classicmodels") or die(mysqli_connect_error());
	
	$sql = "SELECT * FROM orderdetails";
	$result = mysqli_query($conn, $sql);

	$data = array();
	while ($row = mysqli_fetch_object($result))
	{
		array_push($data, $row);
	}
	echo json_encode($data);
	exit();
?>

And these are the results we get when we fetch data from database using Javascript and AJAX:

performance test PHP
performance test javascript
performance test javascript

Conclusion

PerformancePHPJavascript
Page speed74%93%
Time to load page8.6 seconds5.5 seconds
Page size1.24 MB966 KB
Requests14062

[wpdm_package id=’475′]

Load content when scrolled – AJAX, Javascript, PHP & MySQL

In this tutorial, we are going to teach you how you can load the content of div only when user scrolled to that section. For example, you have a lot of dynamic sections in your website, loading them all using PHP is very costly since server has to get a lot of data from database and it will make your website load slower.

Get data using AJAX

Second option was to load all data using AJAX, this will solve the first problem because the website will be loaded instantly and all the sections where dynamic data needs to be displayed will send an AJAX request to get that data and display in relevant section using Javascript.

However, take this example, if your website has 10 sections and users mostly use the first 3 sections. This means that the server is serving 7 extra requests which are not commonly being used by client. It will slowdown the server, possibly crash your website if you have a lot of users. What if we find a way of optimization such that the relevant section will only be loaded when required by user.

How it works

Simply means, request of section will be sent to server only when asked by client to get that data. If user is on first 3 sections, then the ajax will be called only 3 times and server will be serving only 3 requests. Request for section 4 will only be served if user moved or scrolled to that section, otherwise it will not be loaded. It will greatly optimize your website and make it load faster and more responsive.

This tutorial is written in pure Javascript, no jQuery or any other external library has been used. So you can use this tutorial under all Javascript and PHP frameworks.

We have created a sample database called “classicmodels” from where we are going to load the data from 4 tables:

  1. customers
  2. employees
  3. offices
  4. products

The important question here is “How am I going to know when user has scrolled to some div ? And how can I tell the server to get data required in that div ? And how to display it in relevant div ?”. For this, we are going to use Javascript built-in IntersectionObserver object, basically it observes all the nodes in the intersection.

Intersection Observer

Intersection is a visible area in browser, when you open any website, the content which is visible to you is in Intersection. So we are going to add all divs which needs to be loaded dynamically under observation. Once that div intersects, we are going to send a simple AJAX request using Javascript (no jQuery), telling the server what type of data we need and then display the data in that div.

Server side (PHP)

Paste the following code in your server side or back-end PHP file, we have named it “Http.php“. Make sure to change the database credentials.

<?php
	// File name = Http.php

	// Get data from database

	if (isset($_GET["type"]))
	{
		// Connecting with database
		$conn = mysqli_connect("localhost", "root", "", "classicmodels");

		// Just for testing, set a delay for 2 seconds
		sleep(2);

		// Getting all results from relevant table
		// you can perform different queries for each div using $_GET['type'] variable

		$type = $_GET["type"];

		$result = mysqli_query($conn, "SELECT * FROM " . $type);
		$data = array();

		while ($row = mysqli_fetch_object($result))
		{
			array_push($data, $row);
		}

		// Sending response back
		// we also need to send the type back
		echo json_encode(array(
			"data" => $data,
			"type" => $type
		));
		exit();
	}
?>

Client side

Paste the following code in your client side or front-end. Make sure to change the IDs of divs as per your project. Also set server file name as per yours at line 13.

<!-- Create divs which needs to be loaded by ajax -->
<div id="customers" class="loaded-by-ajax"></div>

<div id="employees" class="loaded-by-ajax"></div>

<div id="offices" class="loaded-by-ajax"></div>

<div id="products" class="loaded-by-ajax"></div>
<script>
	// Create observer
	var ajaxObserver = new IntersectionObserver(function (items, self) {
		// Loop through all items in visible area
		for (var a = 0; a < items.length; a++) {
			// Check if div under observation is in visiable area
			if (items[a].isIntersecting) {
				// Get ID
				var id = items[a].target.id;
				
				// Call ajax to get data
				var ajax = new XMLHttpRequest();
				ajax.open("GET", "Http.php?type=" + id, true);

				// Show loading in relevant div before ajax
				document.getElementById(id).innerHTML = "Loading..." + id;

				// This event will be called for each request change status
				ajax.onreadystatechange = function () {
					// Response is received when ready state is 4 and status is 200
					if (this.readyState == 4 && this.status == 200) {
						// Convert JSON string into arrays and objects
						var response = JSON.parse(this.responseText);

						var data = response.data;
						var type = response.type;

						var html = "";
						// Each div might have different layout

						if (type == "customers") {
							html += "<h1>Customers</h1>";

							// Loop through all items
							for (var b = 0; b < data.length; b++) {
								html += "<p>" + data[b].customerName + "</p>";
							}
						} else if (type == "employees") {
							html += "<h1>employees</h1>";

							// Loop through all items
							for (var b = 0; b < data.length; b++) {
								html += "<p>" + data[b].firstName + " " + data[b].lastName + "</p>";
							}
						} else if (type == "offices") {
							html += "<h1>offices</h1>";

							// Loop through all items
							for (var b = 0; b < data.length; b++) {
								html += "<p>" + data[b].city + "</p>";
							}
						} else if (type == "products") {
							html += "<h1>products</h1>";

							// Loop through all items
							for (var b = 0; b < data.length; b++) {
								html += "<p>" + data[b].productName + "</p>";
							}
						}

						// Render the relevant div
						document.getElementById(type).innerHTML = html;
					}
				};

				// Sending the ajax request
				ajax.send();

				// Prevent the div from being observed again
				self.unobserve(items[a].target);
			}
		}
	});

	// Add all loaded-by-ajax divs in observation list
	var loadedByAjax = document.getElementsByClassName("loaded-by-ajax");
	for (var a = 0; a < loadedByAjax.length; a++) {
		ajaxObserver.observe(loadedByAjax[a]);
	}
</script>

That’s how you can load content only when scrolled using Javascript’s “IntersectionObserver”.

Learn how to do the same for images.

Lazy load images – Javascript

[wpdm_package id=’251′]

Use indexes to reduce the overhead on MySQL server

In MySQL database, indexes are used to optimize the database server by reducing the cost for searching data. Take it as an example of index page you see at the end of text books. It contains the page number of important words, so you do not have to check each page of the book to find that word. You just get the page number from index page, and directly lands on that specific page.

Same is the case with indexes in MySQL database. Indexes are applied on column level, so you can specify which values should be indexed. Generally, we apply indexes on those columns whose values are searched most often. For example, in user’s table, one might search for user by his email address. So we can apply the index on email address.

In this tutorial, we are using sample database called classicmodels and the table where we will be working is named as orderdetails. As discussed earlier, indexes are applied on column level, so we will be using column named productCode for this purpose. So let’s get started.

Get all indexes on table

The basic query of getting all indexes applied on some specific table is:

SHOW INDEX FROM table_name;

It will return name of index, sequence number of when applied, column name, integrity and collation etc. The output will be similar as screenshot above.

Even if you haven’t applied any index on any column of that table, you will still see indexes already applied on your table’s primary key (if you have any). They will be applied at the time of creation of table.

You can try running the query on productCode column using EXPLAIN alias and you will see the number of records MySQL server has to go through, just to fetch specific records.

EXPLAIN SELECT * FROM orderDetails WHERE productCode = "S18_3232";

In our case, the query has returned 53 records without applying EXPLAIN clause. And after applying EXPLAIN clause, it will tell that it has searched in 2996 records. So it is an overhead on MySQL server that it has to search in 2996 records just to pull 53 records. So we will be applying index on this column and you will see how much the query will be optimized.

Add index on column

You can either apply index by using ALTER statement or by CREATE INDEX, but we recommend using ALTER since it is been used by other DDL operations too, so it will be easier for you to remember. Also, ALTER helps you when deleting an index from table. Deleting index from column is also discussed at the end of this tutorial.

ALTER TABLE table_name ADD INDEX index_name (column_name);

In this statement, index_name can be anything of your choice. But make sure that it does not have any space and that index name must not be applied on any column before.

Check performance of query

As discussed earlier, we will be applying index on column named productCode. So suppose we have applied the index using the above query, and now we want to see the performance of our query.

After applying the index, you can run again the query but put EXPLAIN clause before the query. So you will performance of query. You will see that the number of rows fetched will be equal (or almost equal) to the number of rows MySQL server has seached.

In our case, MySQL server returned 53 rows using the above query. And the number of rows it has to go through is also 53. Your number may differ based on the size of your table and the query that you are testing.

Also, you will see the column named filtered in result of EXPLAIN query. That tells the percentage of data it has filtered between number of searched rows and number of rows in result.

Delete indexes from column

This will be almost similar to the add index section. You just need to replace the “ADD” with “DROP” and execute the query. In this query, you do not have to specify the name of column, just specify the name of index and it will be done.

ALTER TABLE table_name DROP INDEX;

Try running the show index query again and you will see that specific index will be removed from that column.

Page level cache PHP

Page level cache in PHP means that the most frequent data will be stored in cache. So instead of requesting the same data from database, we will just use the cache to display that data. This will reduce the overhead on database by eliminating number of queries on SQL. Or any other database server you are using.

Cached data storage

Cached data will be stored in files. So it is advised not to store sensitive data, like passwords and credit cards, in the cache. Although no one will know by which name you have saved the cache. But in some circumstances, it can be readable. So we must save that data in a database which is not sensitive. And we can use page level cache in PHP without any fear.

Once data is cached in a file then whenever a user requests that data it will not be fetched from the database. Instead it will be fetched from the cache. This will decrease the page load time and hence will improve the performance of website. For example, if a database query took 6 seconds to fetch the data. Then using this technique you can skip those 6 seconds wait.

Expiry time of cached data

You can also set the expiry time of the cache. So if you have cached some data and now the user is seeing the data from cached files. Now, what if you made some changes in the database ? The user will still be seeing the old cached data ! That is where we need to set the expiry time of the cache. A common practice is to expire the cache after 24 hours but you can customize it as per your needs.

Display page load time

First, we need to find a way to check the actual page load time. So we can get the time when we were at 1st line of the page and we can get the time when we were at the last line of the page. Then we will get the difference between start and end time and we will know the number of seconds it takes to load the page.

<?php

$start_time = time();

?>

<?php

$end_time = time();
echo "<h1>Difference: " . ($end_time - $start_time) . " seconds</h1>";

Create cache

We set the name of the file where we want to store the cache. You can create a separate folder where all caches will be stored, most modern frameworks use this approach. We also will set the expiry time of the cache so it will fetch fresh data after a specified time period.

We will be using output buffering which is used to hold plain HTML before it is displayed in the browser. Whatever content is displayed between ob_start() and ob_get_contents() will be saved in the file.

Then we create a file using write mode and the content of the file will be plain HTML that is rendered on the webpage. So if you open the cache file, you will see that it will have all plain HTML (same as you see when you do “view page source”). That is why it is recommended not to save sensitive data like passwords and credit cards in the cache. Finally, we can close the file object and when you run the script now, you will be able to see a new file created with HTML content.

<?php

$cache_file = "cache.php";
$cache_time = 60; // 1 minute

// Start output buffering
ob_start();

// run all DB queries here

$file = fopen($cache_file, "w");
fwrite($file, ob_get_contents());
fclose($file);

Read cache

We will read the cache only if the file exists and it has not been expired. When you run the script the first time, then the file has not yet been created. So that means that you do not have any cache, after that we will check the expiry time of the cache using file modified time.

Now if the cache is found and it is not expired, then we will display the content from the cache instead of requesting from database. To read the file we have 2 options, one is to use the include or require function and the second is to use readfile function. However, readfile is more secure than include so we will be using this.

You can use else condition if you want to perform some other action, that depends on your needs. But for simplicity, we will stop the script after reading from the cache using the exit() function. Paste the following code after $cache_time variable and before ob_start() function.

<?php

$cache_time = 10; // seconds

if (file_exists($cache_file) && (filemtime($cache_file) + $cache_time > time()))
{
	readfile($cache_file);
	exit();
}

ob_start();

That’s it, now if you run the script you will see that when it loads from the database, it takes more time than when it does from the cache. The script is tested on multiple already created projects and by average it loads 5 seconds faster than using without cache.

Tired of clearing browser cache after making changes in CSS or JS files ?

Prevent browser cache from CSS, JS, and image files

[wpdm_package id=’199′]

Lazy load images – Javascript

Lazy load images means loading images on websites asynchronously. Lazy loading is technique that defers loading of non-critical resources at page load time. Instead, these non-critical resources are loaded at the moment of need. Where images are concerned, “non-critical” is often synonymous with “off-screen”. If you’ve used Lighthouse and examined some opportunities for improvement, you may have seen some guidance in this realm in the form of the Offscreen Images audit.

Intersection observer API

The Intersection Observer API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document’s viewport.

We are going to use 2 images. One will be displayed on top and second will be at the bottom of page. You have to scroll a lot to see the second image. Now you will see that the second image will only be loaded once the user scrolled to the second one. So this will decrease the page load time and hence improves the performance of your website.

First create 2 image tags and give class attribute to access it in Javascript and data-src attribute. It is a custom attribute which we can use to get the actual path of image. DO NOT use src attribute as it will actually load the image, which we do not want. Give both images width as 100% so they will be completely visible inside the browser window.

<!-- Displaying first image -->
<img data-src="image-1.jpg" class="image" alt="1"><br>

<!-- Displaying second image but at bottom -->
<img data-src="image-2.jpg" class="image" alt="2" style="margin-top: 1000px;">

<!-- Image should not overflow the window -->
<style>
	.image {
		width: 100%;
	}
</style>

Load image when scrolled

Then we create a built-in intersection observer which will be called automatically when page is scrolled and will return the items which are visible. We can check if each item is intersection (inside the browser window). We will get the data-src attribute and place it as src attribute, so in this way it will be loaded asynchronously. Once an image is loaded we do not want it to be loaded again, so we will disable it from observing again by calling the unobserve(item) method.

<script>
	// IntersectionObserver is a built-in javascript object
	var observer = new IntersectionObserver(function (items, self) {

		// Loop through all visible items
		for (var a = 0; a < items.length; a++) {

			// Check if item is in visible area of browser
			if (items[a].isIntersecting) {

				// Debug the img tag
				console.log(items[a].target);

				// Get image data-src (custom) attribute
				var src = items[a].target.getAttribute("data-src");

				// Load the image
				items[a].target.setAttribute("src", src);

				// Should not call this function for same image again
				self.unobserve(items[a].target);
			}
		}
	});
</script>

At this point if you run the script, nothing happens. Because we havn’t tell it which items needs to be observed. Since we have given a class attribute to images so we can get all images having that class. Loop through each image and set it to be observed by observer using it’s instance.

<script>
	// Get all images
	var image = document.getElementsByClassName("image");

	// Loop through each image
	for (var a = 0; a < image.length; a++) {
		// Make it observable
		observer.observe(image[a]);
	}
</script>

Conclusion

There are also many libraries available which can do the lazy loading for you. But nothing gives more control than writing your own code. So using this Vanilla JS way you can use intersection observers to lazy load images you want as per required.

[wpdm_package id=’197′]

Use sprites to reduce number of requests on website – Javascript, PHP

Generate sprite image

Sprite is a computer graphics term for a two-dimensional bitmap that is integrated into a larger scene, most often in a 2D video game. Which means that small images are combined into one large image to reduce the number of requests on your server. Sprites helps a lot to reduce the number of HTTP requests.

In CSS sprites, we combine multiple images into a single image. So, if you are using 12 small images in your CSS, it will take 12 requests without sprite. Now if you combine all these images into one image, you will need only 1 request.

The basic principle is, you will combine multiple images into one large image. When you try to access it, the web server will not fetch the new copy of each image everytime you request it. Instead it will fetch just one image which contains all images and you can display them by specifying their position. Same as the image above.

So we will first combine all necessary images into one image and save it as a “sprite.png”. Then we will display the image by telling it’s position. We will be using two files, 1st for combining multiple images into one (save-sprite.php) and 2nd to display the images from sprite.

Generate sprites

First we create an HTML5 canvas tag where all images will be drawn. Give it unique ID to be accessible in Javascript and give it appropriate width and height.

Then we create an array of images which holds width, height and path (src) of each image. We will be looping through this array to automatically draw image on canvas. Also a counter variable to tell the number of current image under process.

Then we get the canvas object and 2D context of canvas. Create a variable named marginLeft to automatically draw the image after the previous one. If this is not specified, then all images will be placed on top of other.

After that, you will create a recursive function that will draw all images inside the array. Inside this function, create a new Image() object and set the image path in src attribute. Call onload function with this image object to wait for the image to fully loaded. The draw the image using drawImage(imageObj, x, y, width, height) function that will render the image on canvas.

Increase margin from left for next image, increment the counter. If there is more images in array then recursion occurs by calling the function itself inside the function. Otherwise if all images are rendered then we will convert that canvas into image and call an AJAX function to save this image data as a sprite.

<!-- Canvas where all images will be drawn -->
<canvas id="myCanvas" width="1000" height="500"></canvas>

<script>

	// An array where all images should be entered
	var images = [{
		width: 308,
		height: 183,
		src: "image1.png"
	}, {
		width: 206,
		height: 260,
		src: "image2.png"
	}];

	// A variable used to get the number of current image
	var count = 0;

	// Get canvas element
	var c = document.getElementById("myCanvas");

	// Get canvas context used for drawing
	var ctx = c.getContext("2d");

	// Give margin to each image so they will be aligned horizontally
	var marginLeft = 0;

	// A recursive function which will keep calling itself
	// until all images are drawn on canvas
	function loadImage() {
		// Create new image object
		var imageObj = new Image();

		// Set the path of image
		imageObj.src = images[count].src;

		// Wait till image fully loaded
		imageObj.onload = function() {
			// Draw image on canvas given image object, x, y, width & height
			ctx.drawImage(imageObj, marginLeft, 0, images[count].width, images[count].height);

			// Increase margin from left
			marginLeft += images[count].width;

			// Increment to next image
			count++;

			// If there is more image to draw
			if (count < images.length) {
				// Recursive occur here
				loadImage();
			} else {
				// All images has been drawn on canvas
				console.log("All images loaded");

				// Convert the canvas into PNG image
				var image = c.toDataURL("image/png", 1);

				// Create AJAX request object
      			var ajax = new XMLHttpRequest();

      			// Set method to POST, file name and asynchnronous
				ajax.open("POST", "save-sprite.php", true);

				// Set headers in POST request
				ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

				// Send the request and pass image data
				ajax.send("image=" + image);

				// Listen for server request changes
				ajax.onreadystatechange = function () {

					// Request is successful if ready state is 4 and status is 200
					if (this.readyState == 4 && this.status == 200) {
						// Print response sent from server
						console.log(this.responseText);
					}
				};
			}
		}
	}

	loadImage();
</script>

Save sprite image

Create a new file named “save-sprite.php” and paste the following code in it. This will give the image data from client and remove the “base64” part from it as that is not necessary. When using AJAX post request we should also convert all spaces into plus sign and then decode the base64 string. Finally you can save the image as separate file.

<?php

$image = $_POST["image"];
$image = explode(";", $image)[1];
$image = explode(",", $image)[1];
$image = str_replace(" ", "+", $image);

$image = base64_decode($image);
file_put_contents("sprite.png", $image);

echo "Done";
?>

Display image from sprite

To display an image we will create a <div> tag and set the background image as sprite. Given the background position allow you to display specific portion of sprite image. For example, if your sprite has 3 images of 100px width each, then your total sprite will be of 300px in width. To display the second image you have give the background position as -100px so it will move the image from left to right.

<style>
	#home {
		width: 308px;
		height: 183px;
		background: url('sprite.png');
		background-repeat: no-repeat;
	}

	#next {
		width: 206px;
		height: 260px;
		background: url('sprite.png');
		background-repeat: no-repeat;
		background-position: -308px 0px;
	}
</style>
<div id="home"></div>
<br>
<div id="next"></div>

Conclusion

Sprites are very useful specially in video games where optimization and performance is very important. So instead of loading all car’s types (Lamborghini, Bugatti, Ferrari, Mclaren) as 4 images they create a single sprite named “cars-sprite.png” which holds all the images of cars. This is just an example, you can categories the sprites as much as required. The point is to send minimum requests on the server.

Hope that helps you in your upcoming or legacy projects to reduce the number of HTTP requests using sprites. If you face any problem, feel free to ask in the comment’s section below.

[wpdm_package id=’195′]