start(); }
  }

  /*  start the timer  */
  function start() {
    $this->start = $this->get_time();
    $this->pause_time = 0;
  }

  /*  pause the timer  */
  function pause() {
    $this->pause_time = $this->get_time();
  }

  /*  unpause the timer  */
  function unpause() {
    $this->start += ($this->get_time() - $this->pause_time);
    $this->pause_time = 0;
  }

  /*  get the current timer value  */
  function get($decimals = 8) {
    return round(($this->get_time() - $this->start),$decimals);
  }

  /*  format the time in seconds  */
  function get_time() {
    list($usec,$sec) = explode(' ', microtime());
    return ((float)$usec + (float)$sec);
  }
}




	// Dummy $wp_filter array with structure to mimick the a real one
	$wp_filter = array(
		// actions 1-4 just echo the action name so you can see which actions get executed in which order
		// action 2 also contains a nested call to the same action to illustrate the bug
		'show_actions'=>array(
			10=>array(
				'dfgjsdfl'=>array('function'=>'action1','accepted_args'=>1),
				'eoivoddw'=>array('function'=>'action2','accepted_args'=>1)
			),
			11=>array(
				'egosfdfn'=>array('function'=>'action3','accepted_args'=>1)
			),
			20=>array(
				'ekragjdt'=>array('function'=>'action4','accepted_args'=>1)
			),
			30=>null
		),
		// actions 5-8 calculate the square root of 2 - just for benchmarking purposes
		// action 6 also contains a nested call to the same action to illustrate the bug
		'test_times'=>array(
			10=>array(
				'dfgjsdfl'=>array('function'=>'action5','accepted_args'=>1),
				'eoivoddw'=>array('function'=>'action6','accepted_args'=>1)
			),
			11=>array(
				'egosfdfn'=>array('function'=>'action7','accepted_args'=>1)
			),
			20=>array(
				'ekragjdt'=>array('function'=>'action8','accepted_args'=>1)
			),
			30=>null
		)
	);
	
	function action1($id) {echo "$id action1\n";}
	function action2($id) {echo "$id action2\n"; if ($id=='out') {global $do_action; $do_action('show_actions',array('in'));}}
	function action3($id) {echo "$id action3\n";}
	function action4($id) {echo "$id action4\n";}
	
	function action5($id) {global $n; sqrt(2); $n++;}
	function action6($id) {global $n; sqrt(2); $n++; if ($id=='out') {global $do_action; $do_action('test_times',array('in'));}}
	function action7($id) {global $n; sqrt(2); $n++;}
	function action8($id) {global $n; sqrt(2); $n++;}
	
	// Number of times to test
	$N=10000;
	
	
	
	// current (broken) implementation of do_action
	$do_action = function($tag,$args) {
	
		global $wp_filter;
		
		reset ($wp_filter[$tag]);
		
		do {
			foreach ( (array) current($wp_filter[$tag]) as $the_ )
				if ( !is_null($the_['function']) )
					call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
		
		} while ( next($wp_filter[$tag]) !== false );
	
	};
	
	echo "old implementation\n";
	$do_action('show_actions',array('out'));
	$n = 0; $timer = new timer(1);
	for ($i=0; $i<$N; $i++) {
		$do_action('test_times',array('out'));
	}
	$time_taken = $timer->get(); $average_time = $time_taken/$n;
	echo "total time: $time_taken sqrts: $n average time: $average_time \n\n\n";
	// note action3 and action4 don't get called in the outer loop
	
	
	


	// working implementation, but $actions_to_execute is a copy of the entire array, so it's expensive
	$do_action = function($tag,$args) {
	
		global $wp_filter;
		
		$actions_for_this_tag = $wp_filter[$tag];
		
		do {
			foreach ( (array) current($actions_for_this_tag) as $the_ )
				if ( !is_null($the_['function']) )
					call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
		} while ( next($actions_to_execute) !== false );
	
	};
	

	echo "copying the array\n";
	$do_action('show_actions',array('out'));
	$n = 0; $timer = new timer(1);
	for ($i=0; $i<$N; $i++) {
		$do_action('test_times',array('out'));
	}
	$time_taken = $timer->get(); $average_time = $time_taken/$n;
	echo "total time: $time_taken sqrts: $n average time: $average_time \n\n\n";
	// all actions get called in both inner and outer loop, but it's slower





	// working implementation, but uses references to array entries, so performance doesn't suffer
	$do_action = function($tag,$args) {
	
		global $wp_filter;
		
		foreach ($wp_filter[$tag] as &$action_to_execute) {
			foreach ((array)$action_to_execute as $the_)
				if ( !is_null($the_['function']) )
					call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
		}
	
	};
	

	echo "using array reference\n";
	$do_action('show_actions',array('out'));
	$n = 0; $timer = new timer(1);
	for ($i=0; $i<$N; $i++) {
		$do_action('test_times',array('out'));
	}
	$time_taken = $timer->get(); $average_time = $time_taken/$n;
	echo "total time: $time_taken sqrts: $n average time: $average_time \n\n\n";
	// all actions get called in both inner and outer loop, and it's faster than the current implementation
	
	
	

?>