mirror of
https://github.com/status-im/react-native.git
synced 2025-01-24 08:18:56 +00:00
Add benchmark for attribute diffing
Summary: Benchmark for testing the attribute diffing algorithm. @public Reviewed By: @vjeux Differential Revision: D2498078
This commit is contained in:
parent
de717a8379
commit
14d2b0e147
@ -0,0 +1,324 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule ReactNativeAttributePayload-benchmark
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var StyleSheet = require('StyleSheet');
|
||||
|
||||
// Various example props
|
||||
|
||||
var small1 = {
|
||||
accessible: true,
|
||||
accessibilityLabel: 'Hello',
|
||||
collapsable: true,
|
||||
};
|
||||
|
||||
var small2 = {
|
||||
accessible: true,
|
||||
accessibilityLabel: 'Hello 2',
|
||||
collapsable: false,
|
||||
needsOffscreenAlphaCompositing: true,
|
||||
};
|
||||
|
||||
var small3 = {
|
||||
accessible: true,
|
||||
accessibilityLabel: 'Hello 2',
|
||||
};
|
||||
|
||||
var medium1 = {
|
||||
...small1,
|
||||
onLayout: function() {},
|
||||
onAccessibilityTap: true,
|
||||
onMagicTap: function() {},
|
||||
collapsable: true,
|
||||
needsOffscreenAlphaCompositing: true,
|
||||
style: {
|
||||
backgroundColor: 'rgba(255, 0, 0, 0.5)'
|
||||
}
|
||||
};
|
||||
|
||||
var medium2 = {
|
||||
...small2,
|
||||
onLayout: function() {},
|
||||
onAccessibilityTap: true,
|
||||
onMagicTap: function() {},
|
||||
collapsable: true,
|
||||
needsOffscreenAlphaCompositing: true,
|
||||
style: {
|
||||
backgroundColor: 'rgba(128, 0, 0, 1)',
|
||||
color: [128, 0, 0],
|
||||
shadowColor: 56,
|
||||
textDecorationColor: 34,
|
||||
tintColor: 45,
|
||||
|
||||
transform: [
|
||||
{perspective: 5},
|
||||
{scale: 5},
|
||||
{scaleX: 10},
|
||||
{scaleY: 10},
|
||||
{translateX: 2},
|
||||
{translateY: 5}
|
||||
],
|
||||
}
|
||||
};
|
||||
|
||||
var medium3 = {
|
||||
...small3,
|
||||
onAccessibilityTap: true,
|
||||
onMagicTap: function() {},
|
||||
needsOffscreenAlphaCompositing: true,
|
||||
style: {
|
||||
backgroundColor: 'rgba(255, 0, 0, 0.5)',
|
||||
color: [128, 0, 0],
|
||||
shadowColor: 56,
|
||||
textDecorationColor: 34,
|
||||
tintColor: 45,
|
||||
|
||||
transform: [
|
||||
{perspective: 5},
|
||||
{scale: 5},
|
||||
{scaleX: 12},
|
||||
{scaleY: 16},
|
||||
{translateX: 10},
|
||||
{translateY: 5}
|
||||
],
|
||||
}
|
||||
};
|
||||
|
||||
var style1 = {
|
||||
|
||||
backgroundColor: 'rgba(10,0,0,1)',
|
||||
borderColor: 'rgba(10,0,0,1)',
|
||||
color: [255, 0, 0],
|
||||
shadowColor: 54,
|
||||
textDecorationColor: 34,
|
||||
tintColor: 45,
|
||||
|
||||
transform: [
|
||||
{perspective: 5},
|
||||
{scale: 5},
|
||||
{scaleX: 2},
|
||||
{scaleY: 3},
|
||||
{translateX: 2},
|
||||
{translateY: 3}
|
||||
],
|
||||
|
||||
};
|
||||
|
||||
var style1b = {
|
||||
|
||||
backgroundColor: 'rgba(10,0,0,1)',
|
||||
borderColor: 'rgba(10,0,0,1)',
|
||||
color: [128, 0, 0],
|
||||
shadowColor: 56,
|
||||
textDecorationColor: 34,
|
||||
tintColor: 45,
|
||||
|
||||
transform: [
|
||||
{perspective: 5},
|
||||
{scale: 5},
|
||||
{scaleX: 10},
|
||||
{scaleY: 10},
|
||||
{translateX: 2},
|
||||
{translateY: 5}
|
||||
],
|
||||
|
||||
};
|
||||
|
||||
var style2 = {
|
||||
|
||||
shadowOffset: { width: 10, height: 15 },
|
||||
|
||||
resizeMode: 'contain', // 'cover'
|
||||
overflow: 'visible', // 'hidden'
|
||||
|
||||
opacity: 0.5,
|
||||
|
||||
width: 123,
|
||||
height: 43,
|
||||
top: 13,
|
||||
left: 43,
|
||||
right: 12,
|
||||
bottom: 123,
|
||||
margin: 13,
|
||||
padding: 53,
|
||||
paddingRight: 523,
|
||||
borderWidth: 63,
|
||||
borderRadius: 123,
|
||||
};
|
||||
|
||||
var style3 = {
|
||||
position: 'absolute', // 'relative'
|
||||
flexDirection: 'row', // 'column'
|
||||
flexWrap: 'wrap', // 'nowrap'
|
||||
justifyContent: 'flex-start', // 'flex-end'
|
||||
alignItems: 'center',
|
||||
alignSelf: 'auto',
|
||||
flex: 0,
|
||||
};
|
||||
|
||||
var style3b = {
|
||||
position: 'relative',
|
||||
flexDirection: 'column',
|
||||
flexWrap: 'nowrap',
|
||||
justifyContent: 'flex-end',
|
||||
};
|
||||
|
||||
var { regStyle2, regStyle3 } = StyleSheet.create({
|
||||
regStyle2: style2,
|
||||
regStyle3: style3
|
||||
});
|
||||
|
||||
var large1 = {
|
||||
...medium1,
|
||||
style: {
|
||||
...medium1.style,
|
||||
...style1,
|
||||
...style2,
|
||||
...style3
|
||||
}
|
||||
};
|
||||
|
||||
var large2 = {
|
||||
...medium2,
|
||||
style: [
|
||||
[regStyle2, style1],
|
||||
regStyle3
|
||||
]
|
||||
};
|
||||
|
||||
var large3 = {
|
||||
...medium3,
|
||||
style: [
|
||||
[regStyle2, style1b],
|
||||
style3
|
||||
]
|
||||
};
|
||||
|
||||
var large4 = {
|
||||
...medium3,
|
||||
style: [
|
||||
[regStyle2, style1b],
|
||||
style3b
|
||||
]
|
||||
};
|
||||
|
||||
// Clones, to test
|
||||
|
||||
var clone = function (obj) {
|
||||
var str = JSON.stringify(obj, function(k, v) {
|
||||
return typeof v === 'function' ? 'FUNCTION' : v;
|
||||
});
|
||||
return JSON.parse(str, function(k, v) {
|
||||
return v === 'FUNCTION' ? function() {} : v;
|
||||
});
|
||||
};
|
||||
|
||||
var small4 = clone(small3);
|
||||
var medium4 = clone(medium3);
|
||||
var large5 = clone(large4);
|
||||
|
||||
// Test combinations
|
||||
|
||||
var variants = {
|
||||
s1: small1,
|
||||
s2: small2,
|
||||
s3: small3,
|
||||
s4: small4,
|
||||
m1: medium1,
|
||||
m2: medium2,
|
||||
m3: medium3,
|
||||
m4: medium4,
|
||||
l1: large1,
|
||||
l2: large2,
|
||||
l3: large3,
|
||||
l4: large4,
|
||||
l5: large5,
|
||||
};
|
||||
|
||||
// Differ
|
||||
|
||||
var validAttributes = require('ReactNativeViewAttributes').UIView;
|
||||
|
||||
var ReactNativeBaseComponent = require('ReactNativeBaseComponent');
|
||||
ReactNativeBaseComponent.prototype.diff =
|
||||
ReactNativeBaseComponent.prototype.computeUpdatedProperties;
|
||||
var Differ = new ReactNativeBaseComponent({
|
||||
validAttributes: validAttributes,
|
||||
uiViewClassName: 'Differ'
|
||||
});
|
||||
|
||||
// Runner
|
||||
|
||||
var numberOfBenchmarks = 0;
|
||||
var totalTimeForAllBenchmarks = 0;
|
||||
var results = {};
|
||||
|
||||
function runBenchmarkOnce(value1, value2) {
|
||||
// Warm up the differ. This is needed if the differ uses state to store the
|
||||
// previous values.
|
||||
Differ.diff({}, value1, validAttributes);
|
||||
var cache = Differ.previousFlattenedStyle;
|
||||
var start = Date.now();
|
||||
for (var i = 0; i < 100; i++) {
|
||||
Differ.diff(value1, value2, validAttributes);
|
||||
Differ.previousFlattenedStyle = cache;
|
||||
}
|
||||
var end = Date.now();
|
||||
return (end - start);
|
||||
}
|
||||
|
||||
function runBenchmark(key1, key2, value1, value2) {
|
||||
var totalTime = 0;
|
||||
var nthRuns = 5;
|
||||
for (var i = 0; i < nthRuns; i++) {
|
||||
totalTime += runBenchmarkOnce(value1, value2);
|
||||
}
|
||||
results[key1 + key2] = totalTime / nthRuns;
|
||||
totalTimeForAllBenchmarks += totalTime / nthRuns;
|
||||
numberOfBenchmarks++;
|
||||
}
|
||||
|
||||
function runAllCombinations() {
|
||||
for (var outerKey in variants) {
|
||||
for (var innerKey in variants) {
|
||||
if (variants.hasOwnProperty(outerKey) &&
|
||||
variants.hasOwnProperty(innerKey)) {
|
||||
runBenchmark(
|
||||
outerKey,
|
||||
innerKey,
|
||||
variants[outerKey],
|
||||
variants[innerKey]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function formatResult() {
|
||||
var str =
|
||||
'Average runtime: ' +
|
||||
(totalTimeForAllBenchmarks / numberOfBenchmarks) +
|
||||
' units\n';
|
||||
|
||||
var worstCase = 0;
|
||||
for (var key in results) {
|
||||
if (results[key] > worstCase) {
|
||||
worstCase = results[key];
|
||||
}
|
||||
}
|
||||
|
||||
str += 'Worst case: ' + worstCase + ' units\n';
|
||||
|
||||
str += 'Per combination:\n';
|
||||
for (var key in results) {
|
||||
str += key + ':\u00A0' + results[key] + ', ';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
runAllCombinations();
|
||||
|
||||
module.exports = formatResult();
|
Loading…
x
Reference in New Issue
Block a user