Posts tagged ‘info’

Getting Directory Tree – Recursive VS Non-Recursive

I took some time to examine between the performance of using a recursive and non recursive method of retrieving a directory tree. Of-course retrieving a directory tree is possible with out using any functions and still be able to get the full tree with unlimited depth possibilities. I made the non recursive piece of code that outputs an array of each file and folder/subfolder of a given directory and a recursive function that calls it self on each new folder found. And then before an after I took a memory usage survey and time lapse of code execution. The folder that i used for testnig had some random folders and files and a freshly downloaded codeigniter frame work. So there were about 360 items in the generated array of files and folders.

Non-Recursive Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$tree=array('folder/');
$folders_to_do = array('folder/');
$current_folder = '';
while(!empty($folders_to_do)){
	$key_of_current_folder = key($folders_to_do);
	$current_folder = $folders_to_do[$key_of_current_folder];
	$folder = scandir($current_folder);
	foreach($folder as $item){
		if(is_dir($current_folder.$item) and $item != '.' and $item != '..'){
			$folders_to_do[] = $current_folder.$item.'/';
			$tree[] = $current_folder.$item.'/';
		}
		if(is_file($current_folder.$item))
			$tree[] = $current_folder.$item;
	}
	unset($folders_to_do[$key_of_current_folder]);
}
sort($tree);

The way it works is very simple. It runs only on 2 loops (while & foreach), 1 array (folders_to_do) and 1 string variable (current_folder) to control what we are scanning. The outer loop will always loop it self as long as it has something to scan, that means if the to-do array is not empty it will loop again. Now inside the while loop we have the regular scandir() function and foreach loop. in the foreach loop when a file is found it is added to the main tree array but if a folder is found then it is not only added to the tree array but is also added to the to-do list. Since the to-do list has something new to scan, the while loop will not brake. At the end when there is no more directories to scan the tree array will contain every folder and file found in the initial directory passed. All that is left to do is to sort the array and you get a neat list of each files and folders of a passed directory.

Recursive:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$tree2 = recursive('folder/');
function recursive($current_folder){
	static $tree = array();
 
	$folder = scandir($current_folder);
	foreach($folder as $item){
		if(is_dir($current_folder.$item) and $item != '.' and $item != '..'){
			$tree[] = $current_folder.$item.'/';
			recursive($current_folder.$item.'/');
		}
		if(is_file($current_folder.$item))
			$tree[] = $current_folder.$item;
	}
	return $tree;
}

This method is also straight forward. It uses a static array inside the function to hold the tree, optionally you can keep passing the tree as an argument if you do not wish to use a static array or if you simple going to use the function multiple times on the same script. The function it self takes in only 1 string variable which is the folder it is going to process. The foreach loop does same thing basically; if it is a file it only adds to the tree array and if it is a folder it adds to the tree array and calls the function with the folder path as teh argument. The recursion concept is no different then any other. It was only simplified ridiculously.

Result Array:

Array
(
    [0] => folder/
    [1] => folder/another folder/
    [2] => folder/another folder/bar file
    [3] => folder/another folder/dddddd/
    [4] => folder/another folder/dddddd/lost track/
    [5] => folder/another folder/dddddd/lost track/last file
    [6] => folder/another folder/hhh/
    [7] => folder/another omg folder/
    [8] => folder/codeigniter omg/
    [9] => folder/codeigniter omg/index.php
...

Both of those codes will produce exactly the same thing but using different amount of memory. Above you can see a steddy array with each folder and file name with full paths.

Performance:
AS I said earlier I had about 360 files and folder combined for testing.

The time in milliseconds took to execute was the same on average of those methods. I refreshed many times and it was always either same or one or the other had few more milliseconds.

The memory usage for the non recursive was 82,512 and for the recursive method it was 116,112. I used the memory_get_usage() function to find those numbers. For each method I took memory usage before the code and after the code. So the results are (after_code – before_code) for first and second methods, just to clarify so no one has questions to how I have come to my conclusion.

82,512 / 116,112 = 0.71 ratio!

All testing was done here: http://www.sandbox.doc776.org/recursion/script.php

PHP Framework CodeIgniter or CodeLighter

I been putting up a fuss lately between choosing to use CodeIgniter or Codelighter.

For those that do not know what CodeIgniter is, it is a very small but powerful MVC based PHP framework for developing web applications. And for those who not sure what CodeLighter is, it is mini version of CodeIgniter, it follows the same syntax in general but the actual framework is minimized to the core.

Some nice things of CodeIgniter is that it has a separate documentation and lots of useful helpers and functions. This is a full framework so everything in it is separated from each part for the code like routes, hooks, core classes and so on.

CodeLighter has every core class like dispatcher controller loader and such placed in one single file. If you are the type that likes simplicity then this is good for you. Even thought it is in one file it is all very well commented and there is no need for documentation separately. It is very easy to go through the code and understand what each thing does and makes it easy to edit to your likes. CodeLighter of course supports the full MVC but more compact on the configuration end. Separate models, helpers, views and controllers. the whole code it self has only 5 directories and 3 files. One is the index that starts the code the actual CodeLighter core classes and MySQL class, everything else is for you to make.

I tried using both of those frameworks to try them out. The first thing to look at is the page render time. I had both frameworks installed on same server and had them only connect to the database and that is it. The render time of each page has a huge difference. CodeIgniter scored on average of 0.07 seconds at all times and CodeLighter Scored 0.005 seconds on average. The difference in loading times is all there and at the end before choosing what you want to use think about what you need it for. The CodeIgniter woulb be good for something heavy that has lots of pages and lots of features. CodeLighter would still be fine but would be better for smaller websites. It is like, what is the point of using a framework if it actually slower then the original code.

Notes:
CodeIgniter is good for beginners that wish to learn MVC structure. Which stands for Module View Controller.
CodeLighter is good for those who are going in depth and wish to know the full mechanics and use a more plain and dynamic MVC framework.

Displaying Page Load Time

It is very simple to show page load times in PHP.

Method 1:
Place this at the very begin of your PHP code:

1
define('STARTING_MICROTIME', get_microtime());

Depending on how you like to organize your code have those functions some where, they are pretty straight forward:

1
2
3
4
5
6
7
8
9
function execution_time()
{
    return sprintf("%01.4f", get_microtime() - STARTING_MICROTIME);
}
function get_microtime()
{
    $time = explode(' ', microtime());
    return doubleval($time[0]) + $time[1];
}

And finally just use the execution_time() function to show the total time elapsed since the script started.

Method 2:
Place this at very beginning of your code.

1
define('PAGE_LOAD_START', microtime(true));

And this where you want to display the render time.

1
<?php echo round((microtime(true) - PAGE_LOAD_START), 4); ?>

This way is easier IMO. Using constants is not necessary, it just avoids problems in namespaces if your code is OOP like.