Ok, thanks for the long detailed email. Let's take a look at this a little
bit at a time. The guiding questions I ask myself to decide whether or not
to make a core change include:

-- How much code does this add
-- Will it affect processing speed
-- How complicated is it
-- Is there a way to do it via plugin
-- Is it really necessary
-- How much power does it add
-- Is there a simpler, easier, or faster way to do it

Using these questions, I'm leaning toward this general approach:

1) I see your point about not being able to add myplugin to $BOLTstopwatch.
It wasn't designed to take a csv list, but if it did, you would have more
fine grained control of what is tracked and what isn't it. Perhaps we could
take it even one step further and look for a match for specific functions
like search or breadcrumb. This way we can set it to track multiple
specific functions/commands in index.php. :)

2) Not convinced of the need to distinguish between {( [( and <(, or at
least not convinced enough to muddy up the markups. This could easily be
managed by a plugin redefining the markups and pointing them to a variant
of a BOLTMfunc function. Using the stopwatch=true parameter in a function
should make it possible to track specific functions... You would set
$BOLTstopWatch='true' in config.php to have (only) those functions/commands
reported.

3) Was unfamiliar with the memory usage capabilities of php. It deserves to
be added to the stopwatch function. It shouldn't affect general processing
speed because it is only called when you use the stopwatch feature.

4) I agree it gives more flexibility to save the stopwatch msg's as an
array of some sort and allow admins to generate their own display function
to sort, filter, and format the output as desired. That's what BoltWire is
all about. I also think this can be done pretty simply. Turn
$BOLTstopWatchMsg into an array, rather than a long string of appended
text. Then write a small script to output it as a message at the end--with
a hook to a custom BOLTstopWatchDisplay function instead if desired.

5) If you can spot specific bugs, let me know. I'll be happy to fix them.
For the most part it seems to work ok.


As for specific code changes you proposed, I interspersed a few comments on
several sections below and then posted my finished code down at the
bottom...


>
>    1. if (isset($BOLTstopWatch)) {
>        BOLTstopWatch('Page construction complete');
>        if (inlist('admin', $BOLTgroups)) $out = str_replace("<body>", 
> "<body><div
>    class='stopwatch'>$BOLTstopWatchMsg</div>", $out);
>        }
>
>
>    1. by
>    if (isset($BOLTstopWatch) || $BOLTstopWatchStats != '' || count(
>    $BOLTstopWatchStats) > 0) {//we can set stopwatch=true in any command
>    without having set $BOLTstopWatch in index.php
>
> I don't think we need another stopwatch variable (BOLTstopWatchStats).

>
>    1.     if (inlist('admin', $BOLTgroups)) $out = str_replace('<body>',
>    '<body>'.BOLTstopWatchOutput(), $out);
>        }
>
> Rather than another function, a hook to your custom function, and a simple
line or two routine to output the default content

>
>    1.
>    function BOLTstopWatch($text) {
>    ## A SPECIAL FUNCTION TO HELP BENCHMARK PROCESSES ON BOLTWIRE SITES.
>    TO USE, SET $BOLTstopWatch="all", $BOLTstopWatch="functions" OR
>    $BOLTstopWatch="commands" IN INDEX.PHP BEFORE CALLING ENGINE
>
> Yes, the instructions here are more accurate. But can allow more options
now like specific functions or commands.

>
>    1.     global $BOLTstopWatch, $BOLTstopWatchStats;
>
>
>    1.
>        if (!isset($BOLTstopWatch) || $BOLTstopWatch === false) return;
>
>
>    1.
>        if (function_exists('myBOLTstopWatch')) return myBOLTstopWatch();
>        $stats = BOLTstopWatchMeasure();
>        if ($BOLTstopWatchStats == '' || count($BOLTstopWatchStats)==0) 
> {//first
>    time
>            $BOLTstopWatchStats[] = array("Resources already spent", $stats
>    [0], $stats[1]);
>
>
>    1.
>            }
>        $BOLTstopWatchStats[] = array($text, $stats[0], $stats[1]);
>        }
>
>
> We don't need a separate variable, but we do need an array.

>
>    1. function BOLTstopWatchMeasure() {
>            if (function_exists('myBOLTstopWatchMeasure')) return
>    myBOLTstopWatchMeasure();
>            return array(microtime(true),memory_get_usage());
>        }
>
>    function BOLTstopWatchOutput() {
>        if (function_exists('myBOLTstopWatchOutput')) return
>    myBOLTstopWatchOutput();
>        global $BOLTstopWatchStats,$BOLTstopWatchMsg;
>        $globalstats = 'You are using PHP '.PHP_VERSION.'<br />Total
>    duration: '.formatDecimal(microtime(true)-$BOLTstopWatchStats[0][1]).'
>    seconds<br />Memory usage: '.formatBytes(memory_get_usage()).' / '.
>    formatBytes(memory_get_peak_usage()).'<br />';
>
>
>    1.
>
>        $c = count($BOLTstopWatchStats);
>        for($i = 1; $i < $c; $i++) {
>            $stats = $BOLTstopWatchStats[$i];
>            $prevStats = $BOLTstopWatchStats[$i-1];
>
>
>    1.
>            $BOLTstopWatchMsg .= '<li>Duration: '.formatDecimal($stats[1]-
>    $prevStats[1]).' seconds - Memory: '.formatBytes($stats[2]-$prevStats[2
>    ]).' - <span style="font-size:larger;">'.$stats[0].'</span><ul>';
>
>
>    1.
>            foreach($stats[3] as $execStats) {
>                $execs[$execStats[0]]++;
>
>
>    1.
>                $BOLTstopWatchMsg .= '<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'.
>    $execStats[0].' took '.formatDecimal($execStats[1]).' seconds and used
>    '.formatBytes($execStats[2]).' of memory</li>';
>                }
>            $BOLTstopWatchMsg .= '</ul></li>';
>            }
>
>        $stopWatchText = '<div
>    class="stopwatch"><strong>StopWatch:</strong><br />'.$globalstats.'<br
>    /><ul>'.$BOLTstopWatchMsg.'</ul></div>';
>        return $stopWatchText;
>        }
>
>    function formatDecimal($number, $length = 6) {
>        $lengthBeforeDot = strlen($number);
>        if(strpos($number,'.')) $lengthBeforeDot = strlen(substr($number,0,
>    strpos($number,'.')));
>
>        $length = $length - ($lengthBeforeDot - 1);
>
>
>    1.
>        return number_format($number, $length, '.', '\'');
>        }
>
>
>
>    1. function formatBytes($bytes, $precision = 3) {
>
>
>    1.
>        $units = array('B', 'KB', 'MB', 'GB', 'TB');
>        $bytes = max($bytes, 0);
>        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
>        $pow = min($pow, count($units) - 1);
>
>        // Uncomment one of the following alternatives
>        $bytes /= pow(1024, $pow);
>        // $bytes /= (1 << (10 * $pow));
>
>
>    1.
>
>        if($units[$pow]== 'B') $precision = $precision+1;
>
>        $res = round($bytes, $precision);
>
>
>    1.
>
>        return formatDecimal($res, $precision) . ' ' . $units[$pow];
>
>

>
>    1.     }
>
>
I think we can do this much more simply... I'm not too concerned about
detailed formatting. Only admins are looking at this and the raw data
should be ok.

>
>    1. Replace
>    if ($zone != 'COMMAND' && $BOLTstopWatch != '') {
>            if ($args['stopwatch'] == 'true' || inlist($BOLTstopWatch,
>    'all,functions')) {
>
>
>    1.
>                global $BOLTswi; // stop watch index...
>                $i = $i + 1;
>                $m = microtime();
>                $BOLTswi[$i] = substr($m, -10) . substr($m, 2, 4);
>                }
>            }
>
>
>    1.
>    by
>    if ($zone != 'COMMAND' && $BOLTstopWatch != '') {
>            if ($args['stopwatch'] == 'true' || inlist('all',$BOLTstopWatch
>    ) || inlist('functions',$BOLTstopWatch)) $functionStartStats =
>    BOLTstopWatchMeasure();
>            }
>    2. Replace
>    if ($zone != 'COMMAND' && $BOLTstopWatch != '') {
>            if ($args['stopwatch'] == 'true' || inlist($BOLTstopWatch,
>    'all,functions')) {
>
>
>    1.
>                $m = microtime();
>                $t2 = substr($m, -10) . substr($m, 2, 4);
>                $t = ($t2 - $BOLTswi[$i]) / 10000;
>
>
>    1.
>                $BOLTstopWatchMsg = $BOLTstopWatchMsg . "<br
>    />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function $function took $t seconds";
>                }
>            }
>
>
> I wish we had a way to indent still further when a function is nested
within another function (such as a search template).

>
>    1. if ($zone != 'COMMAND' && $BOLTstopWatch != '') {
>            if ($args['stopwatch'] == 'true' || inlist('all',$BOLTstopWatch
>    ) || inlist('functions',$BOLTstopWatch)) {
>                $functionEndStats = BOLTstopWatchMeasure();
>
>
>    1.
>                if(isset($args['functype'])) $function = $args['functype'].
>    $function;
>                $BOLTstopWatchStats[count($BOLTstopWatchStats)-1][3][] =
>    array("function $function",($functionEndStats[0]-$functionStartStats[0
>    ]),$functionEndStats[1]-$functionStartStats[1],print_r($args,true));
>                }
>            }
>
>
>    1.
>    2. Replace
>
>
>    1.
>    if ($args['stopwatch'] == 'true' || inlist($BOLTstopWatch,
>    'all,commands')) {
>            global $BOLTswi; // stop watch index...
>            $i = $i + 1;
>            $m = microtime();
>            $BOLTswi[$i] = substr($m, -10) . substr($m, 2, 4);
>            }
>    by
>
>
>    1. if ($args['stopwatch'] == 'true' || inlist('all',$BOLTstopWatch) ||
>    inlist('commands',$BOLTstopWatch)) $commandStartStats =
>    BOLTstopWatchMeasure();
>    2. Replace
>
>
>    1.
>    if ($args['stopwatch'] == 'true' || inlist($BOLTstopWatch,
>    'all,commands')) {
>            $m = microtime();
>            $t2 = substr($m, -10) . substr($m, 2, 4);
>            $t = ($t2 - $BOLTswi[$i]) /
>
>
Ok I think I've processed all your suggestions. Here's what seems to me a
much simple approach that seems to work ok:

1) Use this in BOLTfunc:

function BOLTfunc($function, $args, $zone='') { ## PREAPARES A CALL TO A
FUNCTION. HAS MANY OUTPUT OPTIONS INCLUDING: FALSE, SOURCE, NOLINES, CSV, &
ESCAPE global $pageLink, $BOLTtoolmap, $pageArray, $BOLTstopWatch,
$BOLTstopWatchMsg; if ($zone != 'COMMAND' && $BOLTstopWatch != '') { if
($args['stopwatch'] == 'true' || inlist('all', $BOLTstopWatch) ||
inlist('functions', $BOLTstopWatch) || inlist($function, $BOLTstopWatch)) {
global $BOLTswi; // stop watch index... $i = $i + 1; $m = microtime();
$BOLTswi[$i] = substr($m, -10) . substr($m, 2, 4); } } $function =
strtolower($function); if ($BOLTtoolmap['f'][$function] != '') $function =
$BOLTtoolmap['f'][$function]; else $function = BOLTtranslate($function, '',
true); if (function_exists("BOLTF$function")) { $BOLTfunction =
"BOLTF$function"; if (BOLTauth($pageLink, $function, 'functions')) $value =
$BOLTfunction($args); else return; } if (isset($args['output'])) { if
(preg_match('/^\~\~([0-9]+)\~\~$/', $value) == 1) $value =
BOLTescape($value, false); $value = BOLToutput($value, $args); if
($args['output'] == 'escape') $value = BOLTescape($value); } if ($zone !=
'COMMAND' && $BOLTstopWatch != '') { if ($args['stopwatch'] == 'true' ||
inlist('all', $BOLTstopWatch) || inlist('functions', $BOLTstopWatch) ||
inlist($function, $BOLTstopWatch)) { $m = microtime(); $t2 = substr($m,
-10) . substr($m, 2, 4); $t = ($t2 - $BOLTswi[$i]) / 10000; $mem =
ceil(memory_get_usage()/1000) . ' KB'; $BOLTstopWatchMsg[] =
Array("function: $function", '', "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$t", $mem);
} } if ($args['output'] !== 'false') return $value; }

and this in BOLTcommand:

function BOLTcommand($do, $args, $field) { ## PREPARES A COMMAND TO BE
CALLED, LIKE BOLTFUNC global $BOLTstopWatch, $BOLTstopWatchMsg; if
($BOLTstopWatch != '') { if ($args['stopwatch'] == 'true' || inlist('all',
$BOLTstopWatch) || inlist('commands', $BOLTstopWatch) || inlist($do,
$BOLTstopWatch)) { global $BOLTswi; // stop watch index... $i = $i + 1; $m
= microtime(); $BOLTswi[$i] = substr($m, -10) . substr($m, 2, 4); } }
$value = BOLTinit($args[1], $args['value']); if
(preg_match('/\~\~([0-9]+)\~\~/', $value) == 1) $value = BOLTescape($value,
false); if (function_exists($do)) $value = $do($value, $field, $args); if
(isset($args['output'])) $value = BOLToutput($value, $args); if
($args['escape'] === 'true') $value = BOLTescape($value); else $value =
BOLTescape($value, false); if ($BOLTstopWatch != '') { if
($args['stopwatch'] == 'true' || inlist('all', $BOLTstopWatch) ||
inlist('commands', $BOLTstopWatch) || inlist($do, $BOLTstopWatch)) { $m =
microtime(); $t2 = substr($m, -10) . substr($m, 2, 4); $t = ($t2 -
$BOLTswi[$i]) / 10000; $mem = ceil(memory_get_usage()/1000) . ' KB';
$BOLTstopWatchMsg[] = Array("command: $do", '',
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$t", $mem); } } if ($args['output'] !==
'false') return $value; }

2) Retrieve memory used in the BOLTstopwatch function and save all
information in an array like this (it actually simplifies the code a slight
bit):

function BOLTstopWatch($text) {
## A SPECIAL FUNCTION TO HELP BENCHMARK PROCESSES ON BOLTWIRE SITES. TO
USE, SET $BOLTstopWatch='all'; IN INDEX.PHP BEFORE CALLING ENGINE (or true,
functions, commands, search, breadcrumb, etc)
global $BOLTstopWatch, $BOLTstopWatchMsg, $BOLTstopWatchTime;
if (! $BOLTstopWatch) return;
$now = (time() . substr(microtime(), 0, 5)) * 1000;
$display = $now;
if (strlen($display) == 14) $display = $display . '0';
elseif (strlen($display) == 13) $display = $display . '00';
elseif (strlen($display) == 12) $display = $display . '000';
if ($BOLTstopWatchTime == '') {
$BOLTstopWatchTime = $now;
return;
}
if ($now != $BOLTstopWatchTime) {
$duration = ($now - $BOLTstopWatchTime) / 10000;
if (strlen($duration) == 5) $duration = $duration . '0';
elseif (strlen($duration) == 4) $duration = $duration . '00';
elseif (strlen($duration) == 3) $duration = $duration . '000';
}
else $duration = "0.0000";
$BOLTstopWatchTime = $now;
$mem = ceil(memory_get_usage()/1000) . ' KB';
$BOLTstopWatchMsg[] = Array($text, $display, $duration, $mem);
}

3) Change the output script to something like:

if (isset($BOLTstopWatch)) {
BOLTstopWatch('Page construction complete');
if (inlist('admin', $BOLTgroups)) {
if (function_exists('myStopWatchDisplay')) $out =
myStopWatchDisplay($BOLTstopWatchMsg, $out);
else {
foreach($BOLTstopWatchMsg as $swm) $sw_out = $sw_out . '<br />' . "$swm[2]
seconds - $swm[3] memory - $swm[0]";
$out = str_replace("<body>", "<body><div class='stopwatch'>$sw_out</div>",
$out);
}
}
}

This accomplishes fast but flexible control of what is tracked and when. It
returns memory usage information. And it gives a hook to a custom display
as needed by the admin.

What do you think?

Cheers,
Dan

-- 
You received this message because you are subscribed to the Google Groups 
"BoltWire" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/boltwire.
For more options, visit https://groups.google.com/d/optout.

Reply via email to