<?php

error_reporting( E_ALL );

$trials = 1000000;

define( 'WP_MEMORY_LIMIT', '32M' );

$functions = array( 'wp_function', 'patch_function_original', 'patch_function_new', 'patch_function_new_complete', 'wp_convert_hr_to_bytes', 'map', 'aaron' );
$comparisons = array(
	'-1'		=> '-1',
	'100'		=> '32M',
	'1m'		=> '32M',
	'7.5G'		=> '7.5G',
	'234k'		=> '32M',
	'94556M'	=> '94556M',
	'128 M'		=> '128 M',
	'52428800'	=> '52428800',
);

$normalize_mem = create_function( '$val', '$val = trim($val); $last = strtolower($val[strlen($val)-1]); switch($last) { case \'g\': $val *= 1024; case \'m\': $val *= 1024; case \'k\': $val *= 1024; return max(0, (int) $val); }' );

for ( $count = 0; $count < count( $functions ); $count++ ) {
	$function = $functions[$count];
	
	foreach ( $comparisons as $size => $answer ) {
		ini_set( 'memory_limit', $size );
		
		$function();
		
		$result = ini_get( 'memory_limit' );
		
		echo "$function  $size => $answer ($result) ";
		
		if ( $answer == $result )
			echo "Success\n";
		else
			echo "Fail\n";
	}
	echo "\n";
}

$results = array();

for ( $count = 0; $count < $trials; $count++ ) {
	$function = $functions[ rand( 0, count( $functions ) - 1 ) ];
	
	if ( ! isset( $results[$function] ) ) {
		$results[$function] = array(
			'trials'		=> 0,
			'total_time'	=> 0,
			'trial_time'	=> array(),
			'success_count'	=> 0,
			'total_count'	=> 0,
		);
	}
	
	run_trial( $function );
}

foreach ( $functions as $function ) {
	$result = $results[$function];
	
	echo "$function\n";
	echo "==========================\n";
	echo "Trials:           {$result['trials']}\n";
	echo "Total Time:       {$result['total_time']}\n";
	echo "Average Time:     " . ( $result['total_time'] / $result['trials'] ) . "\n";
	echo "Runs per Sec:     " . ( 1 / ( $result['total_time'] / $result['trials'] ) ) . "\n";
	
	if ( $result['total_count'] > 0 )
		echo "Success Rate:     " . ( $result['success_count'] / $result['total_count'] ) . "\n";
	
	if ( isset( $results['wp_function']['total_time'] ) )
		echo "Speed Difference: " . ( ( $result['total_time'] - $results['wp_function']['total_time'] ) / $results['wp_function']['total_time'] ) . "\n";
	
	echo "\n";
}



function run_trial( $function, $count = 10 ) {
	global $results, $comparisons;
	
	
	$time = 0;
	
	$success_count = $total_count = 0;
	
	for ( $i = 0; $i < $count; $i++ ) {
		foreach ( $comparisons as $size => $answer ) {
			ini_set( 'memory_limit', $size );
			
			$start = microtime( true );
			$function();
			$end = microtime( true );
			
			$time += $end - $start;
			
			
			if ( $answer == ini_get( 'memory_limit' ) )
				$success_count++;
			$total_count++;
		}
	}
	
	
	$results[$function]['trials']++;
	$results[$function]['total_time'] += $time;
	$results[$function]['success_count'] += $success_count;
	$results[$function]['total_count'] += $total_count;
}


function wp_function() {
	if ( function_exists('memory_get_usage') && ( (int) @ini_get('memory_limit') < abs(intval(WP_MEMORY_LIMIT)) ) )
		@ini_set('memory_limit', WP_MEMORY_LIMIT);
}

function patch_function_original() {
	global $normalize_mem;
	
	if (
		function_exists( 'memory_get_usage' )
		&& ( function_exists( $normalize_mem ) )
		&& ( $normalize_mem( @ini_get( 'memory_limit' ) ) < $normalize_mem( WP_MEMORY_LIMIT ) )
	) {
		@ini_set('memory_limit', WP_MEMORY_LIMIT);
	}
	unset( $normalize_mem );
}

function patch_function_new() {
	if ( function_exists( 'memory_get_usage' ) ) {
		$memory_limit = @ini_get( 'memory_limit' );
		
		if ( $memory_limit > -1 ) {
			switch( substr( $memory_limit, -1 ) ) {
				case 'M': case 'm':
					$memory_limit = (int) $memory_limit;
					break;
				case 'G': case 'g':
					$memory_limit = (int) $memory_limit * 1024;
					break;
				case 'K': case 'k':
					$memory_limit = (int) $memory_limit / 1024;
					break;
				default:
					$memory_limit = (int) $memory_limit / 1048576;
			}
			
			if ( $memory_limit < abs( intval( WP_MEMORY_LIMIT ) ) )
				@ini_set( 'memory_limit', WP_MEMORY_LIMIT );
		}
	}
}

function patch_function_new_complete() {
	$memory_limit = @ini_get( 'memory_limit' );
	
	if ( $memory_limit > -1 ) {
		$unit = strtolower( substr( $memory_limit, -1 ) );
		
		$wp_memory_limit = WP_MEMORY_LIMIT;
		$wp_unit = strtolower( substr( $wp_memory_limit, -1 ) );
		
		if ( 'm' == $unit )
			$memory_limit *= 1048576;
		else if ( 'g' == $unit )
			$memory_limit *= 1073741824;
		else if ( 'k' == $unit )
			$memory_limit *= 1024;
		
		if ( 'm' == $wp_unit )
			$wp_memory_limit *= 1048576;
		else if ( 'g' == $wp_unit )
			$wp_memory_limit *= 1073741824;
		else if ( 'k' == $wp_unit )
			$wp_memory_limit *= 1024;
		
		if ( (int) $memory_limit < (int) $wp_memory_limit )
			@ini_set( 'memory_limit', WP_MEMORY_LIMIT );
	}
}

function wp_convert_hr_to_bytes() {
	$size = strtolower(@ini_get('memory_limit'));
	$bytes = (int) $size;
	if ( strpos($size, 'k') !== false )
		$bytes = intval($size) * 1024;
	elseif ( strpos($size, 'm') !== false )
		$bytes = intval($size) * 1024 * 1024;
	elseif ( strpos($size, 'g') !== false )
		$bytes = intval($size) * 1024 * 1024 * 1024;
	
	$wp_size = strtolower(@ini_get('memory_limit'));
	$wp_bytes = (int) $wp_size;
	if ( strpos($wp_size, 'k') !== false )
		$wp_bytes = intval($wp_size) * 1024;
	elseif ( strpos($wp_size, 'm') !== false )
		$wp_bytes = intval($wp_size) * 1024 * 1024;
	elseif ( strpos($wp_size, 'g') !== false )
		$wp_bytes = intval($wp_size) * 1024 * 1024 * 1024;
	
	if ( $bytes < $wp_bytes )
		@ini_set( 'memory_limit', WP_MEMORY_LIMIT );
}

function map() {
	$memory_limit = @ini_get( 'memory_limit' );
	
	if ( $memory_limit > -1 ) {
		$map = array('g' => 1073741824, 'm' => 1048576, 'k'=> 1024);
		
		$unit = strtolower( substr( $memory_limit, -1 ) );
		
		$wp_memory_limit = WP_MEMORY_LIMIT;
		$wp_unit = strtolower( substr( $wp_memory_limit, -1 ) );
		
		$memory_limit *= isset($map[$unit]) ? $map[$unit] : 1;
		$wp_memory_limit *= isset($map[$wp_unit]) ? $map[$wp_unit] : 1;
		
		if ( (int) $memory_limit < (int) $wp_memory_limit )
			@ini_set( 'memory_limit', WP_MEMORY_LIMIT );
	}
}

function aaron() {
	$memory_limit = @ini_get( 'memory_limit' );
	
	if ( $memory_limit > -1 ) {
		$symbol = array('B', 'K', 'M', 'G');
		
		$unit = strtolower( substr( $memory_limit, -1 ) );
		
		$wp_memory_limit = WP_MEMORY_LIMIT;
		$wp_unit = strtolower( substr( $wp_memory_limit, -1 ) );
		
		$memory_limit *= pow(1024, array_search(strtoupper($unit), $symbol));
		$wp_memory_limit *= pow(1024, array_search(strtoupper($wp_unit), $symbol));
		
		if ( (int) $memory_limit < (int) $wp_memory_limit )
			@ini_set( 'memory_limit', WP_MEMORY_LIMIT );
	}
}
