Skip to content

Commit 7ea7254

Browse files
committed
Optimize mapObj
I did some profiling of StyleSheet.create and noticed that mapObj was a good target for optimization. Methodology I created an HTML document with the following code in it: ```html <script type="text/javascript" src="./dist/aphrodite.umd.js"></script> <!-- setup --> <script type="text/javascript"> // build up an array of styles objects to run our test on var styles = []; for (var i = 0; i < 10000; i += 1) { styles.push({ [`a${Math.random()}`]: { [`a${Math.random()}`]: Math.random(), [`b${Math.random()}`]: String(Math.random()), [`c${Math.random()}`]: String(Math.random()), }, [`b${Math.random()}`]: { [`a${Math.random()}`]: Math.random(), [`b${Math.random()}`]: String(Math.random()), [`c${Math.random()}`]: String(Math.random()), }, [`c${Math.random()}`]: { [`a${Math.random()}`]: Math.random(), [`b${Math.random()}`]: String(Math.random()), [`c${Math.random()}`]: String(Math.random()), }, }); } </script> <!-- test --> <script type="text/javascript"> setTimeout(() => { performance.mark('start_run'); for (var i = 0; i < styles.length; i += 1) { // prevent caching optimizations eval(''); performance.mark('start_stylesheet_create'); aphrodite.StyleSheet.create(styles[i]); performance.mark('end_stylesheet_create'); performance.measure( 'aphrodite.StyleSheet.create', 'start_stylesheet_create', 'end_stylesheet_create' ); performance.clearMarks('start_stylesheet_create', 'end_stylesheet_create'); } performance.mark('end_run'); performance.measure(`Benchmark ${styles.length}`, 'start_run', 'end_run'); performance.clearMarks(); }); </script> ``` Then, looking at the timeline tool in Chrome, I loaded the page a few times before and after this change. Similarly, I ran a CPU profile before and after this change through 5 page reloads each. In this test, the timeline was not very helpful, I think because of the testing overhead. However, the CPU profile was very clear. Before this change, normalizing for the callback showing up in a different part of the profile, `mapObj` took ~317ms and after this change, it drops to ~211ms. `StyleSheet.create` drops from ~755ms to ~670ms or roughly 11% faster. The rest of the time in `StyleSheet.create` is spent in `murmurhash2_32_gc` and `hashObject`.
1 parent e30ed7b commit 7ea7254

1 file changed

Lines changed: 9 additions & 10 deletions

File tree

src/util.js

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,18 @@ type ObjectMap = { [id:string]: any };
1010
// {K1: V1, K2: V2, ...} -> [[K1, V1], [K2, V2]]
1111
export const objectToPairs = (obj /* : ObjectMap */) /* : Pairs */ => Object.keys(obj).map(key => [key, obj[key]]);
1212

13-
// [[K1, V1], [K2, V2]] -> {K1: V1, K2: V2, ...}
14-
const pairsToObject = (pairs /* : Pairs */) /* : ObjectMap */ => {
15-
const result = {};
16-
pairs.forEach(([key, val]) => {
17-
result[key] = val;
18-
});
19-
return result;
20-
};
21-
2213
export const mapObj = (
2314
obj /* : ObjectMap */,
2415
fn /* : PairsMapper */
25-
) /* : ObjectMap */ => pairsToObject(objectToPairs(obj).map(fn))
16+
) /* : ObjectMap */ => {
17+
const keys = Object.keys(obj);
18+
const mappedObj = {};
19+
for (let i = 0; i < keys.length; i += 1) {
20+
const [newKey, newValue] = fn([keys[i], obj[keys[i]]]);
21+
mappedObj[newKey] = newValue;
22+
}
23+
return mappedObj;
24+
}
2625

2726
// Flattens an array one level
2827
// [[A], [B, C, [D]]] -> [A, B, C, [D]]

0 commit comments

Comments
 (0)