<commit_before><?php

/* A simple PrestoPHP class for adding execution duration profiling to debugging output.

	Usage:
	
		Profiler::track($key, $extra);
	
	* Turns a timer on to track duration of process identified by $key (turns it off if it has been running.
	* $extra is an optional array that is JSON encoded and added to debug output

*/
class Profiler {

	private static $processes = array();

	public static function track($key, $extra = null) {
		if (!array_key_exists($key, self::$processes)) {
			// initialize
			self::$processes[$key] = (object) array(
				'duration' => 0,
				'duration_units' => 'microseconds',
				'last_started' => microtime(true) * 1000000,
				'state' => 'running',
				'extra' => array()
			);
		}
		
		
		$p = &self::$processes[$key];
		
		if ($p->state === 'running') {
			// toggle off
			$p->duration += microtime(true) * 1000000 - $p->last_started;
			$p->state = 'stopped';
		}
		else {
			// toggle on
			$p->last_started = microtime(true) * 1000000;
			$p->state = 'running';
		}
	
		if (is_array($extra))
			$p['extra'] = array_merge($p['extra'], $extra);
	}
	
	public static function profiles() {
		
		if (empty(self::$processes)) return;
	
		foreach (self::$processes as &$p) {
			if ($p->state === 'running') {
				// calc current durations for output
				$p->duration += microtime(true) * 1000000 - $p->last_started;
			}
		}
		
		return self::$processes;<commit_msg>Issue #47. I have moved away from the toggle on/off approach and now provide static methods track (for initial) stop, and restart. Also exposes a static accessor for a given keyed thing being tracked.<commit_after><?php
include_once(PRESTO_BASE.'/_helpers.php');
define('PROFILER_TRACE_KEY', '_profiler_trace');

/* A simple PrestoPHP class for adding execution duration profiling to debugging output.

	Usage:
	
		Profiler::track($key, $extra); // initialize and start tracking execution time (with optional extra debugging data)
		Profiler::stop($key); // stop tracking execution time
		Profiler::restart($key, $extra); // restart tracking execution time (optional $extra data is merged with existing optional $extra debugging data)
		Profiler::profile($key); // return current profile data
	
	* $extra is an optional array that is JSON encoded and added to debug output
	* All profile data is automatically added to Presto trace output if Presto trace is enabled (see _config)

*/
class Profiler {

	private static $processes = array();

	/*
		Set up inital tracking of a process identified by $key and start timing duration.
	*/
	public static function track($key, $extra = null) {
	
		if (isset($extra) && !is_array($extra)) {
			presto_lib::_trace( __METHOD__, "Failed to track [$key]: optional extra data must be an array.");
			return;
		}
			
		if (!array_key_exists($key, self::$processes)) {
			// initialize
			self::$processes[$key] = (object) array(
				'duration' => 0,
				'duration_units' => 'microseconds',
				'last_started' => microtime(true) * 1000000,
				'state' => 'running',
				'extra' => $extra
			);
		}
		else
			presto_lib::_trace( __METHOD__, "[$key]: is already being tracked.");
	}
	
	/*
		Turn timer off for process identified by $key and calculate duration since the last time it was turned on.
	*/
	public static function stop($key) {

		if (empty(self::$processes[$key])) {
			presto_lib::_trace( __METHOD__, "Failed to stop [$key]: it isn't being tracked.");
			return;
		}
		
		$p = &self::$processes[$key];
		
		if ($p->state === 'running') {
			// toggle off
			$p->duration += microtime(true) * 1000000 - $p->last_started;
			$p->state = 'stopped';
		}
	}
	
	/*
		Restart timer for process identified by $key.
		
		* Optional $extra debugging data is merged with any set in Profiler::track
	*/
	public static function restart($key, $extra = null) {
		
		if (empty(self::$processes[$key])) {
			presto_lib::_trace( __METHOD__, "Failed to restart [$key]: it isn't being tracked.");
			return;
		}
	
		if (isset($extra) && !is_array($extra)) {
			presto_lib::_trace( __METHOD__, "Failed to restart [$key]: optional extra data must be an array.");
			return;
		}
		
		$p = &self::$processes[$key];
		
		if ($p->state === 'stopped') {
			// toggle on
			$p->last_started = microtime(true) * 1000000;
			$p->state = 'running';
		}
	
		if (is_array($extra))
			$p['extra'] = array_merge($p['extra'], $extra);
	}
	
	/*
		Return the profile of the process identified by $key.
	*/
	public static function profile($key) {
		
		if (empty(self::$processes[$key])) return;
		
		$p = &self::$processes[$key];
	
		if ($p->state === 'running') {
			// calc current durations for output
			$p->duration += microtime(true) * 1000000 - $p->last_started;
		}

		return $p;
	}
	
	/*
		Return all profile data.
	*/
	public static function profiles() {
		
		if (empty(self::$processes)) return;
	
		foreach (self::$processes as &$p) {
			if ($p->state === 'running') {
				// calc current durations for output
				$p->duration += microtime(true) * 1000000 - $p->last_started;
			}
		}
		
		return self::$processes;
{'fraction_non_alphanumeric': 0.15128712871287128, 'fraction_numerical': 0.013267326732673267, 'mean_word_length': 3.5669077757685352, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3049412', 'n_tokens_mistral': 1875, 'n_tokens_neox': 1575, 'n_words': 501}