in MotionMark/resources/runner/motionmark.js [26:287]
function(version, options, testData)
{
this._iterationsSamplers = [];
this._options = options;
this._results = null;
this._version = version;
this._targetFrameRate = options["frame-rate"] || 60;
this._systemFrameRate = options["system-frame-rate"] || 60;
if (testData) {
this._iterationsSamplers = testData;
this._processData();
}
}, {
push: function(suitesSamplers)
{
this._iterationsSamplers.push(suitesSamplers);
},
_processData: function()
{
this._results = {};
this._results[Strings.json.results.iterations] = [];
var iterationsScores = [];
this._iterationsSamplers.forEach(function(iteration, index) {
var testsScores = [];
var testsLowerBoundScores = [];
var testsUpperBoundScores = [];
var result = {};
this._results[Strings.json.results.iterations][index] = result;
var suitesResult = {};
result[Strings.json.results.tests] = suitesResult;
for (var suiteName in iteration) {
var suiteData = iteration[suiteName];
var suiteResult = {};
suitesResult[suiteName] = suiteResult;
for (var testName in suiteData) {
if (!suiteData[testName][Strings.json.result])
this.calculateScore(suiteData[testName]);
suiteResult[testName] = suiteData[testName][Strings.json.result];
delete suiteData[testName][Strings.json.result];
testsScores.push(suiteResult[testName][Strings.json.score]);
testsLowerBoundScores.push(suiteResult[testName][Strings.json.scoreLowerBound]);
testsUpperBoundScores.push(suiteResult[testName][Strings.json.scoreUpperBound]);
}
}
result[Strings.json.score] = Statistics.geometricMean(testsScores);
result[Strings.json.scoreLowerBound] = Statistics.geometricMean(testsLowerBoundScores);
result[Strings.json.scoreUpperBound] = Statistics.geometricMean(testsUpperBoundScores);
iterationsScores.push(result[Strings.json.score]);
}, this);
this._results[Strings.json.version] = this._version;
this._results[Strings.json.fps] = this._targetFrameRate;
this._results[Strings.json.score] = Statistics.sampleMean(iterationsScores.length, iterationsScores.reduce(function(a, b) { return a + b; }));
this._results[Strings.json.scoreLowerBound] = this._results[Strings.json.results.iterations][0][Strings.json.scoreLowerBound];
this._results[Strings.json.scoreUpperBound] = this._results[Strings.json.results.iterations][0][Strings.json.scoreUpperBound];
},
calculateScore: function(data)
{
var result = {};
data[Strings.json.result] = result;
var samples = data[Strings.json.samples];
function findRegression(series, profile) {
var minIndex = Math.round(.025 * series.length);
var maxIndex = Math.round(.975 * (series.length - 1));
var minComplexity = series.getFieldInDatum(minIndex, Strings.json.complexity);
var maxComplexity = series.getFieldInDatum(maxIndex, Strings.json.complexity);
if (Math.abs(maxComplexity - minComplexity) < 20 && maxIndex - minIndex < 20) {
minIndex = 0;
maxIndex = series.length - 1;
minComplexity = series.getFieldInDatum(minIndex, Strings.json.complexity);
maxComplexity = series.getFieldInDatum(maxIndex, Strings.json.complexity);
}
var complexityIndex = series.fieldMap[Strings.json.complexity];
var frameLengthIndex = series.fieldMap[Strings.json.frameLength];
var regressionOptions = { desiredFrameLength: 1000/this._targetFrameRate };
if (profile)
regressionOptions.preferredProfile = profile;
return {
minComplexity: minComplexity,
maxComplexity: maxComplexity,
samples: series.slice(minIndex, maxIndex + 1),
regression: new Regression(
series.data,
function (data, i) { return data[i][complexityIndex]; },
function (data, i) { return data[i][frameLengthIndex]; },
minIndex, maxIndex, regressionOptions)
};
}
// Convert these samples into SampleData objects if needed
[Strings.json.complexity, Strings.json.controller].forEach(function(seriesName) {
var series = samples[seriesName];
if (series && !(series instanceof SampleData))
samples[seriesName] = new SampleData(series.fieldMap, series.data);
});
var isRampController = this._options["controller"] == "ramp";
var predominantProfile = "";
if (isRampController) {
var profiles = {};
data[Strings.json.controller].forEach(function(regression) {
if (regression[Strings.json.regressions.profile]) {
var profile = regression[Strings.json.regressions.profile];
profiles[profile] = (profiles[profile] || 0) + 1;
}
});
var maxProfileCount = 0;
for (var profile in profiles) {
if (profiles[profile] > maxProfileCount) {
predominantProfile = profile;
maxProfileCount = profiles[profile];
}
}
}
var regressionResult = findRegression(samples[Strings.json.complexity], predominantProfile);
var calculation = regressionResult.regression;
result[Strings.json.complexity] = {};
result[Strings.json.complexity][Strings.json.regressions.segment1] = [
[regressionResult.minComplexity, calculation.s1 + calculation.t1 * regressionResult.minComplexity],
[calculation.complexity, calculation.s1 + calculation.t1 * calculation.complexity]
];
result[Strings.json.complexity][Strings.json.regressions.segment2] = [
[calculation.complexity, calculation.s2 + calculation.t2 * calculation.complexity],
[regressionResult.maxComplexity, calculation.s2 + calculation.t2 * regressionResult.maxComplexity]
];
result[Strings.json.complexity][Strings.json.complexity] = calculation.complexity;
result[Strings.json.complexity][Strings.json.measurements.stdev] = Math.sqrt(calculation.error / samples[Strings.json.complexity].length);
result[Strings.json.fps] = data.targetFPS || 60;
if (isRampController) {
var timeComplexity = new Experiment;
data[Strings.json.controller].forEach(function(regression) {
timeComplexity.sample(regression[Strings.json.complexity]);
});
var experimentResult = {};
result[Strings.json.controller] = experimentResult;
experimentResult[Strings.json.score] = timeComplexity.mean();
experimentResult[Strings.json.measurements.average] = timeComplexity.mean();
experimentResult[Strings.json.measurements.stdev] = timeComplexity.standardDeviation();
experimentResult[Strings.json.measurements.percent] = timeComplexity.percentage();
const bootstrapIterations = 2500;
var bootstrapResult = Regression.bootstrap(regressionResult.samples.data, bootstrapIterations, function(resampleData) {
var complexityIndex = regressionResult.samples.fieldMap[Strings.json.complexity];
resampleData.sort(function(a, b) {
return a[complexityIndex] - b[complexityIndex];
});
var resample = new SampleData(regressionResult.samples.fieldMap, resampleData);
var bootstrapRegressionResult = findRegression(resample, predominantProfile);
return bootstrapRegressionResult.regression.complexity;
}, .8);
result[Strings.json.complexity][Strings.json.bootstrap] = bootstrapResult;
result[Strings.json.score] = bootstrapResult.median;
result[Strings.json.scoreLowerBound] = bootstrapResult.confidenceLow;
result[Strings.json.scoreUpperBound] = bootstrapResult.confidenceHigh;
} else {
var marks = data[Strings.json.marks];
var samplingStartIndex = 0, samplingEndIndex = -1;
if (Strings.json.samplingStartTimeOffset in marks)
samplingStartIndex = marks[Strings.json.samplingStartTimeOffset].index;
if (Strings.json.samplingEndTimeOffset in marks)
samplingEndIndex = marks[Strings.json.samplingEndTimeOffset].index;
var averageComplexity = new Experiment;
var averageFrameLength = new Experiment;
var controllerSamples = samples[Strings.json.controller];
controllerSamples.forEach(function (sample, i) {
if (i >= samplingStartIndex && (samplingEndIndex == -1 || i < samplingEndIndex)) {
averageComplexity.sample(controllerSamples.getFieldInDatum(sample, Strings.json.complexity));
var smoothedFrameLength = controllerSamples.getFieldInDatum(sample, Strings.json.smoothedFrameLength);
if (smoothedFrameLength && smoothedFrameLength != -1)
averageFrameLength.sample(smoothedFrameLength);
}
});
var experimentResult = {};
result[Strings.json.controller] = experimentResult;
experimentResult[Strings.json.measurements.average] = averageComplexity.mean();
experimentResult[Strings.json.measurements.concern] = averageComplexity.concern(Experiment.defaults.CONCERN);
experimentResult[Strings.json.measurements.stdev] = averageComplexity.standardDeviation();
experimentResult[Strings.json.measurements.percent] = averageComplexity.percentage();
experimentResult = {};
result[Strings.json.frameLength] = experimentResult;
experimentResult[Strings.json.measurements.average] = 1000 / averageFrameLength.mean();
experimentResult[Strings.json.measurements.concern] = averageFrameLength.concern(Experiment.defaults.CONCERN);
experimentResult[Strings.json.measurements.stdev] = averageFrameLength.standardDeviation();
experimentResult[Strings.json.measurements.percent] = averageFrameLength.percentage();
result[Strings.json.score] = averageComplexity.score(Experiment.defaults.CONCERN);
result[Strings.json.scoreLowerBound] = result[Strings.json.score] - averageFrameLength.standardDeviation();
result[Strings.json.scoreUpperBound] = result[Strings.json.score] + averageFrameLength.standardDeviation();
}
},
get data()
{
return this._iterationsSamplers;
},
get results()
{
if (this._results)
return this._results[Strings.json.results.iterations];
this._processData();
return this._results[Strings.json.results.iterations];
},
get options()
{
return this._options;
},
get version()
{
return this._version;
},
_getResultsProperty: function(property)
{
if (this._results)
return this._results[property];
this._processData();
return this._results[property];
},
get score()
{
return this._getResultsProperty(Strings.json.score);
},
get scoreLowerBound()
{
return this._getResultsProperty(Strings.json.scoreLowerBound);
},
get scoreUpperBound()
{
return this._getResultsProperty(Strings.json.scoreUpperBound);
}
});