performance.js revision ad1c6b0e13792902836033020a7b4204e311e733
// -- Shorthand & Private Variables --------------------------------------------
Obj = Y.Object,
EVT_CLEAR = 'clear',
EVT_END = 'end',
EVT_FINISH = 'finish',
EVT_RESULT_ADD = 'resultAdd',
EVT_START = 'start',
EVT_STOP = 'stop',
MODE_ITERATION = 1,
ACTIVE_SUITE = 'activeSuite',
COMPLETE = 'complete',
RESULTS = 'results',
RUNNING = 'running',
suites = {},
xhrCache = {},
yqlCache = {},
yqlQueue = {};
function Performance() {
}
Performance.ATTRS = {
activeSuite: {
readOnly: true
},
complete: {
},
readOnly: true,
value: false
},
mode: {
}
},
results: {
readOnly: true,
value: {}
},
running: {
getter: function () {
},
readOnly: true
}
};
// -- Protected Properties -------------------------------------------------
_queue : [],
_sandboxes: [],
_stopped : false,
// -- Public Methods -------------------------------------------------------
/**
* Clears results from the most recent test suite and stops running tests if
* tests are currently running.
*
* @method clearResults
*/
clearResults: function () {
this.stop();
},
/**
* Starts running the specified test suite.
*
* @method start
* @param {String} suiteName test suite to run
*/
var tests = {};
return;
}
if (!suite) {
return;
}
this.clearResults();
// Queue up all the tests from each group, interleaving them so that
// we run all tests with the same name from all groups before moving on
// to the next test.
}
}, this);
}, this);
}, this);
}, this);
// Start running tests.
this._runNextTest();
},
/**
* Stops running tests if tests are currently running.
*
* @method stop
*/
stop: function () {
this._stopped = true;
}
},
// -- Protected Methods ----------------------------------------------------
_finish: function () {
var sandbox;
}
this._queue = [];
if (!this._stopped) {
this.fire(EVT_FINISH);
}
this._stopped = false;
},
push,
// Note: test is now a shallow clone, but functions are still references
// to the original test functions. Don't modify them.
// Add a warmup iteration if desired.
i += 1;
}
// This function will create or reuse a sandbox for each test iteration
// and then push that iteration onto the queue, while also providing a
// handy closure to make async sandbox configuration easier.
push = function () {
var poll,
preload = {};
// Use one sandbox for all iterations of a given test unless the
// useStrictSandbox option is true.
}));
// TODO: clone this
if (test.preloadUrls) {
});
});
poll = Y.later(Y.config.pollInterval || 15, this, function (sandbox) { // note the local sandbox reference being passed in
}
}, sandbox, true);
}
}
// Push the test and its sandbox onto the queue.
warmup : test.warmup && !(test.warmup = false) // intentional assignment, sets warmup to false for future iterations
});
};
while (i--) {
}
},
_runNextTest: function (pending) {
// If no pending iteration was passed in and the queue was empty, we're
// done running tests.
this._finish();
return;
}
// Wait for this iteration's sandbox to be ready, then set up and run
// the test. If the sandbox is already ready, the callback will execute
// immediately.
var count,
// Run the setup function if there is one and if it hasn't already
// been run for this iteration.
if (test.asyncSetup) {
// The setup function is asynchronous, so we'll pause the
// iteration while it runs, then restart the iteration once
// the setup function finishes successfully.
if (result === false) {
// Setup function returned false, so abort the test.
this._runNextTest();
} else {
// Restart the iteration.
this._runNextTest(iteration);
}
}, this));
return;
// Setup function returned false, so abort the test.
this._runNextTest();
return;
}
}
if (mode === MODE_ITERATION) {
// In iteration mode, we time the execution of each individual
// iteration. This is the default mode.
}, this));
// In time mode, we run as many iterations as we can within the
// specified duration rather than profiling each iteration. For
// some tests, this can be a more accurate way of arriving at
// consistent benchmark results.
//
// This is wrapped in a setTimeout to allow some breathing room
// between tests and allow other UI events to be processed.
setTimeout(Y.bind(function () {
}, this), 100);
}
}, this);
},
// -- Protected Callbacks & Event Handlers ---------------------------------
// If the test has a teardown function, run it.
}
// Destroy the sandbox unless we need to reuse it for another iteration.
if (test.useStrictSandbox) {
}
// If this was a warmup iteration, continue without collecting the
// results.
this._runNextTest();
return;
}
// Collect the results of the iteration.
if (!groupResults) {
}
calls : 0,
failures: 0,
points : []
};
if (profileData.returnValue === false) {
// A false return value indicates that the test failed.
} else {
}
});
this.fire(EVT_RESULT_ADD, {
});
}
this._runNextTest();
},
mean,
// If the test has a teardown function, run it.
}
// Destroy the sandbox unless we need to reuse it for another iteration.
if (test.useStrictSandbox) {
}
// If this was a warmup iteration, continue without collecting the
// results.
this._runNextTest();
return;
}
// Collect the results of the time test.
if (!groupResults) {
}
mediandev: 0.00,
stdev : 0.00,
variance : 0.00
};
this.fire(EVT_RESULT_ADD, {
});
this._runNextTest();
}
}, {
// -- Public Static Constants ----------------------------------------------
NAME : 'performance',
// -- Public Static Methods ------------------------------------------------
addTestGroup: function (config) {
// Test suites are created on demand.
if (!suite) {
groups: {}
};
}
// Assign a unique id to each test.
});
return config;
},
},
getTestSuite: function (name) {
},
getTestSuites: function () {
},
// -- Protected Static Methods ---------------------------------------------
/**
* Returns an object hash containing the mean, median, sample variance, sample
* standard deviation, and median absolute deviation of the values in the
* specified array.
*
* @method _analyzePoints
* @param {Array} values values to analyze
* @return {Object}
* @protected
*/
_analyzePoints: function (values) {
var i,
max = null,
mean,
min = null,
sum = 0,
// Find the sum, max, and min.
i = len;
while (i--) {
}
}
}
// And the mean.
// And the sum of the squared differences of each value from the mean.
i = len;
sum = 0;
while (i--) {
}
// And finally the sample variance and sample standard deviation.
return {
};
},
/**
* Returns the median of the values in the specified array of numbers, or
* <code>null</code> if the array is empty.
*
* @method _median
* @param {Array} values array of numbers
* @return {Number|null}
* @protected
*/
// Note: This implementation is naïve and does a full sort before
// finding the median. If we ever start working with very large arrays,
// this should be rewritten to use a linear selection algorithm.
if (!len) {
return null;
}
return a > b;
});
} else { // even number of items
}
},
/**
* Returns the median absolute deviation of the values in the specified
* array of numbers, or <code>null</code> if the array is empty.
*
* @method _medianDeviation
* @param {Array} values array of numbers
* @return {Number|null}
* @protected
*/
_medianDeviation: function (values) {
var deviations = [],
// Find the absolute deviations from the median of the set.
while (i--) {
}
// The median of the deviations is the median absolute deviation.
},
/**
* Performs a synchronous XMLHttpRequest GET for the specified URL.
*
* @method _xhrGet
* @param {String} url
* @return {String|null} response body, or <code>null</code> on error
* @protected
*/
// Create a local XMLHttpRequest so we can overwrite it later if
// necessary without affecting the global scope.
XMLHttpRequest = function () {
try {
return new ActiveXObject('Msxml2.XMLHTTP.6.0');
} catch (ex1) {}
try {
return new ActiveXObject('Msxml2.XMLHTTP.3.0');
} catch (ex2) {}
try {
return new ActiveXObject('Msxml2.XMLHTTP');
} catch (ex3) {}
Y.error("This browser doesn't support XMLHttpRequest.");
};
}
// Redefine _xhrGet to avoid running the XHR feature detection again.
// If the URL is already in the cache, return it.
}
var xhr = new XMLHttpRequest();
try {
// Synchronous request.
} catch (ex) {
Y.log("XMLHttpRequest failed. Make sure you're running on an HTTP server, not the local filesystem.", 'warn', 'performance');
}
// Cache the response and return it.
} else {
return null;
}
};
},
/**
* Performs a cross-domain GET request via a YQL proxy. This allows us to
* preload external resources resources and have full control over when
* they're parsed and executed. Responses are cached for the life of the
* pageview.
*
* @method _yqlGet
* @param {String} url url to get
* @param {Function} callback callback to execute when the response is
* received
* @protected
*/
// If this URL is already in the cache, return it.
// If a request for this URL is already queued, add the callback to
// the original request's callback stack instead of creating a new
// request.
} else {
// Add this URL and its callback to the request queue and send the
// request. It'll be removed from the queue when the response
// arrives.
(new Y.yql("use '" + YQL_XDR_DATATABLE + "'; select * from xdr where url = '" + url + "'", function (result) {
var callback;
// Cache the result.
// Call each callback in this request's stack.
}
// Remove the request from the queue.
}));
}
}
});
Y.Performance = Performance;
}, '@VERSION@', {
requires: [
'base', 'event-custom-base', 'gallery-sandbox', 'gallery-yql', 'later'
]
});