Here is the timing code that I have written, and it works excellent
for my Pretty Diff tool.  The following example is slightly modified.
The "z" variable of proctime is the name of the containing function,
and must be supplied as a string literal.

var startTime = (function () {
        var d = new Date(),
            t = d.getTime();
        return t;
    }()),
    proctime = function (z) {
        var d = "",
            e = "",
            g = new Date(),
            b = ((g.getTime() - startTime) / 1000).toFixed(3),
            plural = function (x, y) {
                if (x > 1) {
                    x = x + y + "s ";
                } else {
                    x = x + y + " ";
                }
                return x;
            },
            minute = function () {
                d = (b / 60).toFixed(1);
                d = Number(d.toString().split(".")[0]);
                b = (b - (d * 60)).toFixed(3);
                d = plural(d, " minute");
            };

        if (b >= 60 && b < 3600) {
            minute();
        } else if (b >= 3600) {
            e = (b / 3600).toFixed(1);
            e = Number(e.toString().split(".")[0]);
            b = b - (e * 3600);
            e = plural(e, " hour");
            minute();
        }
        return "<p><strong>" + z + ":</strong> <em>" + e + d + b + "</
em> seconds</p>";
    };

This outputs the length of execution in a human readable format
accurate to nearest milisecond.  For greatest accuracy you will
definately need to make sure that the "startTime" variable is the
first component of a given function to be fed into the interpreter.
The proctime function can likely be fed into the interpreter at any
time since it must be fed prior to the functions return or exit
anyways.  For the greatest accuracy proctime must be executed directly
between the last moment of computation and the exit of the wrapping
function.

The above describes the absolute ideal scenario for time testing a
single function.  That is absolutely necessary, but insufficient to
your objectives.  You will need the above to happen at each and every
function execution automatically and fed into a single container.
Let's call this so called container the 'output array'.  The output
array would be easy enough to load such as:
output.push(proctime('profiler.add'));

So far we know how to achieve the most accurate per function result in
a human readable form.  There are two problems left unsolved:

1) Automatic attachment - For simplicity and accuracy it is necessary
to attach the startTime execution to each and every function
automatically in a nonconflicting manner.  This means the variable
name must be unique at each attachment so that a child function does
not reset the timer for a containing function.  This sound incorrect
since each instance of startTime can be uniquely scoped to the
immediate function, however this does necessarily address pointer
interference from proctime if there is interfering leakage elsewhere
in the function or if proctime is mistakenly trapped in a looping
condition.  The proctime function must also be automatically attached
to each function and executed as described above.  While proctime does
not have to be uniquely named it must correctly point to the startTime
variable that is of the same scope only.  I do not play with
prototypes, but it looks like this automation would need to go into
the function's prototype.  Just don't forget to correctly add the line
executing proctime and placement relative to the timing of execution,
as previous described, is absolutely essential for accuracy.

2) Scope Contamination - The more important problem that likely has no
solution is the problem of contamination versus scope distance.  The
attachment of additional executing segments of code increases memory
consumption and processing time.  This means the results of a profiler
are likely accurate at the lowest scoped functions, and is severely
inaccurate at higher levels based upon scope depth and the number of
function executions.  For example my Pretty Diff application is
entirely contained in a single function, but this application has
great depth.  This means the deepest functions are likely accurate in
the measurement of their timing, but some of these deeper functions
execute more than once before to the global function exits.  The
output array would properly indicate such.  The proctime function
likely executes so fast that it cannot by itself be measured in
miliseconds, however this execution would become certainly noticable
as the frequency of executions increase.  This increase to the total
weight of execution would certainly delay the exit from the complete
application thereby distorting the measurement for the total
application.

The only solution to this second problem is to manually execute to the
profiling at each scope uniquely and then append the results from each
execution.  Since this solution absolutely defeats automation it is
not a solution worth considering.

This is everything you absolutely need to know about execution time
profiling.  You can find a similar answer more simply by using the
JSLint tool and looking at the complexity score assigned for each
function in the report.  Unfortunately, this scoring is based upon
condition complexity and not time length.  The score also does not
take scope, inheritance, or closure into account; which I completely
empathize with as a logical design decision for pointing to complexity
reduction via containment.  Even though I do empathize with and
understand that design decision I do disagree with it since it is so
easy to point between scope levels in JavaScript and there is a
definite performance hit for doing so.

Austin Cheney, CISSP
http://prettydiff.com/

-- 
To view archived discussions from the original JSMentors Mailman list: 
http://www.mail-archive.com/[email protected]/

To search via a non-Google archive, visit here: 
http://www.mail-archive.com/[email protected]/

To unsubscribe from this group, send email to
[email protected]

Reply via email to