Files
react-native/Libraries/ReactNative/__benchmarks__/ReactNativeAttributePayload-benchmark.js
Sebastian Markbage 6c5024ec58 Refactor Attribute Processing (Step 1)
Summary: Concolidate the creation of the "update payload" into
ReactNativeAttributePayload which now has a create
and a diff version. The create version can be used by
both mountComponent and setNativeProps. This means that
diffRawProperties moves into ReactNativeAttributePayload.

Instead of storing previousFlattenedStyle as memoized
state in the component tree, I recalculate it every
time. This allows better use of the generational GC.
However, it is still probably a fairly expensive
technique so I will follow it up with a diff that
walks both nested array trees to do the diffing in a
follow up.

This is the first diff of several steps.

@​public

Reviewed By: @vjeux

Differential Revision: D2440644

fb-gh-sync-id: 1d0da4f6e2bf716f33e119df947c044abb918471
2015-10-06 10:28:27 -07:00

319 lines
5.7 KiB
JavaScript

/**
* 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 Differ = require('ReactNativeAttributePayload');
// 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();