Skip to content

Commit 6c3d998

Browse files
authoredJan 20, 2019
chore: Add performance benchmark to diff-sequences package (#7603)
* chore: Add performance benchmark to diff-sequences * Change require to refer to build directory * Update CHANGELOG.md * Add Facebook copyright header to index.js file * Replace process.stdout.write with console.log * Add link to 7627 as a way to restart CI :)
1 parent f4cf46a commit 6c3d998

File tree

5 files changed

+231
-2
lines changed

5 files changed

+231
-2
lines changed
 

‎CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@
163163
- `[*]` Standardize file names ([#7316](https://github.com/facebook/jest/pull/7316), [#7266](https://github.com/facebook/jest/pull/7266), [#7238](https://github.com/facebook/jest/pull/7238), [#7314](https://github.com/facebook/jest/pull/7314), [#7467](https://github.com/facebook/jest/pull/7467), [#7464](https://github.com/facebook/jest/pull/7464)), [#7471](https://github.com/facebook/jest/pull/7471))
164164
- `[docs]` Add `testPathIgnorePatterns` in CLI documentation ([#7440](https://github.com/facebook/jest/pull/7440))
165165
- `[docs]` Removed misleading text about `describe()` grouping together tests into a test suite ([#7434](https://github.com/facebook/jest/pull/7434))
166-
- `[*]` Replace as many `Object.assign` with object spread as possible
166+
- `[diff-sequences]` Add performance benchmark to package ([#7603](https://github.com/facebook/jest/pull/7603))
167+
- `[*]` Replace as many `Object.assign` with object spread as possible ([#7627](https://github.com/facebook/jest/pull/7627))
167168
- `[ci]` Initial support for Azure Pipelines ([#7556](https://github.com/facebook/jest/pull/7556))
168169

169170
### Performance

‎packages/diff-sequences/package.json

+8-1
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,12 @@
1818
"engines": {
1919
"node": ">= 6"
2020
},
21-
"main": "build/index.js"
21+
"main": "build/index.js",
22+
"scripts": {
23+
"perf": "node --expose-gc perf/index.js"
24+
},
25+
"devDependencies": {
26+
"benchmark": "^2.1.4",
27+
"diff": "^4.0.1"
28+
}
2229
}
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
## Benchmark time for `diff-sequences` versus `diff`
2+
3+
A ratio less than 1.0 means `diff-sequences` is faster.
4+
5+
### n = 20
6+
7+
| name | % | ratio | improved | rme | baseline | rme |
8+
| :----- | ---: | :----- | :-------- | ----: | :-------- | ----: |
9+
| delete | 20% | 0.1824 | 3.0639e-6 | 1.11% | 1.6795e-5 | 0.78% |
10+
| insert | 20% | 0.1367 | 2.5786e-6 | 0.75% | 1.8866e-5 | 0.85% |
11+
| delete | 40% | 0.1015 | 3.0534e-6 | 1.00% | 3.0090e-5 | 0.70% |
12+
| insert | 40% | 0.0791 | 2.6722e-6 | 0.61% | 3.3791e-5 | 0.56% |
13+
| delete | 80% | 0.0410 | 2.8870e-6 | 0.93% | 7.0411e-5 | 0.72% |
14+
| insert | 80% | 0.0371 | 2.5786e-6 | 0.83% | 6.9431e-5 | 0.62% |
15+
| change | 10% | 0.1504 | 2.8703e-6 | 0.71% | 1.9087e-5 | 0.83% |
16+
| change | 20% | 0.1706 | 3.2637e-6 | 0.78% | 1.9127e-5 | 0.62% |
17+
| change | 50% | 0.0944 | 1.2012e-5 | 0.55% | 1.2724e-4 | 0.76% |
18+
| change | 100% | 0.0522 | 1.5422e-5 | 0.61% | 2.9566e-4 | 0.66% |
19+
20+
### n = 200
21+
22+
| name | % | ratio | improved | rme | baseline | rme |
23+
| :----- | ---: | :----- | :-------- | ----: | :-------- | ----: |
24+
| delete | 20% | 0.1524 | 7.2866e-5 | 0.75% | 4.7797e-4 | 0.80% |
25+
| insert | 20% | 0.1226 | 6.1561e-5 | 0.58% | 5.0198e-4 | 0.66% |
26+
| delete | 40% | 0.1118 | 1.5674e-4 | 0.67% | 1.4020e-3 | 0.58% |
27+
| insert | 40% | 0.0894 | 1.2906e-4 | 0.64% | 1.4435e-3 | 0.53% |
28+
| delete | 80% | 0.0796 | 3.0119e-4 | 0.58% | 3.7852e-3 | 0.52% |
29+
| insert | 80% | 0.0734 | 2.4713e-4 | 0.67% | 3.3653e-3 | 0.54% |
30+
| change | 10% | 0.1572 | 7.2965e-5 | 0.48% | 4.6426e-4 | 0.73% |
31+
| change | 20% | 0.1446 | 7.0056e-5 | 0.69% | 4.8456e-4 | 0.53% |
32+
| change | 50% | 0.0764 | 6.5638e-4 | 0.67% | 8.5946e-3 | 0.70% |
33+
| change | 100% | 0.0525 | 1.1160e-3 | 0.51% | 2.1249e-2 | 0.63% |
34+
35+
### n = 2000
36+
37+
| name | % | ratio | improved | rme | baseline | rme |
38+
| :----- | ---: | :----- | :-------- | ----: | :-------- | ----: |
39+
| delete | 20% | 0.0669 | 3.4073e-3 | 0.54% | 5.0922e-2 | 0.54% |
40+
| insert | 20% | 0.0588 | 2.8273e-3 | 0.51% | 4.8111e-2 | 0.46% |
41+
| delete | 40% | 0.0517 | 1.1048e-2 | 0.52% | 2.1367e-1 | 0.47% |
42+
| insert | 40% | 0.0460 | 9.1469e-3 | 0.37% | 1.9878e-1 | 0.26% |
43+
| delete | 80% | 0.0563 | 2.7426e-2 | 0.56% | 4.8674e-1 | 0.36% |
44+
| insert | 80% | 0.0506 | 2.2208e-2 | 0.35% | 4.3888e-1 | 0.47% |
45+
| change | 10% | 0.0716 | 3.1267e-3 | 1.21% | 4.3652e-2 | 0.56% |
46+
| change | 20% | 0.0621 | 3.0197e-3 | 0.72% | 4.8652e-2 | 0.45% |
47+
| change | 50% | 0.0083 | 5.4250e-2 | 0.62% | 6.5595e+0 | 3.60% |
48+
| change | 100% | 0.0493 | 1.0534e-1 | 0.71% | 2.1362e+0 | 0.21% |

‎packages/diff-sequences/perf/index.js

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
// Make sure to run node with --expose-gc option!
9+
10+
// The times are reliable if about 1% relative mean error if you run it:
11+
12+
// * immediately after restart
13+
// * with 100% battery charge
14+
// * not connected to network
15+
16+
/* eslint import/no-extraneous-dependencies: "off" */
17+
18+
const Benchmark = require('benchmark');
19+
20+
const diffBaseline = require('diff').diffLines;
21+
const diffImproved = require('../build/index.js').default;
22+
23+
const testBaseline = (a, b) => {
24+
const benchmark = new Benchmark({
25+
fn() {
26+
diffBaseline(a, b);
27+
},
28+
name: 'baseline',
29+
onCycle() {
30+
global.gc(); // after run cycle
31+
},
32+
onStart() {
33+
global.gc(); // when benchmark starts
34+
},
35+
});
36+
37+
benchmark.run({async: false});
38+
39+
return benchmark.stats;
40+
};
41+
42+
const testImproved = function(a, b) {
43+
const benchmark = new Benchmark({
44+
fn() {
45+
// Split string arguments to make fair comparison with baseline.
46+
const aItems = a.split('\n');
47+
const bItems = b.split('\n');
48+
49+
const isCommon = (aIndex, bIndex) => aItems[aIndex] === bItems[bIndex];
50+
51+
// This callback obviously does less than baseline `diff` package,
52+
// but avoiding double work and memory churn is the goal.
53+
// For example, `jest-diff` has had to split strings that `diff` joins.
54+
const foundSubsequence = () => {};
55+
56+
diffImproved(aItems.length, bItems.length, isCommon, foundSubsequence);
57+
},
58+
name: 'improved',
59+
onCycle() {
60+
global.gc(); // after run cycle
61+
},
62+
onStart() {
63+
global.gc(); // when benchmark starts
64+
},
65+
});
66+
67+
benchmark.run({async: false});
68+
69+
return benchmark.stats;
70+
};
71+
72+
const writeHeading2 = () => {
73+
console.log('## Benchmark time for `diff-sequences` versus `diff`\n');
74+
console.log('A ratio less than 1.0 means `diff-sequences` is faster.');
75+
};
76+
77+
const writeHeading3 = n => {
78+
console.log(`\n### n = ${n}\n`);
79+
console.log('| name | % | ratio | improved | rme | baseline | rme |');
80+
console.log('| :--- | ---: | :--- | :--- | ---: | :--- | ---: |');
81+
};
82+
83+
const writeRow = (name, percent, statsImproved, statsBaseline) => {
84+
const {mean: meanImproved, rme: rmeImproved} = statsImproved;
85+
const {mean: meanBaseline, rme: rmeBaseline} = statsBaseline;
86+
const ratio = meanImproved / meanBaseline;
87+
88+
console.log(
89+
`| ${name} | ${percent}% | ${ratio.toFixed(
90+
4,
91+
)} | ${meanImproved.toExponential(4)} | ${rmeImproved.toFixed(
92+
2,
93+
)}% | ${meanBaseline.toExponential(4)} | ${rmeBaseline.toFixed(2)}% |`,
94+
);
95+
};
96+
97+
const testDeleteInsert = (tenths, more, less) => {
98+
// For improved `diff-sequences` package, delete is often slower than insert.
99+
const statsDeleteImproved = testImproved(more, less);
100+
const statsDeleteBaseline = testBaseline(more, less);
101+
writeRow('delete', tenths * 10, statsDeleteImproved, statsDeleteBaseline);
102+
103+
// For baseline `diff` package, many insertions is serious perf problem.
104+
// However, the benchmark package cannot accurately measure for large n.
105+
const statsInsertBaseline = testBaseline(less, more);
106+
const statsInsertImproved = testImproved(less, more);
107+
writeRow('insert', tenths * 10, statsInsertImproved, statsInsertBaseline);
108+
};
109+
110+
const testChange = (tenths, expected, received) => {
111+
const statsImproved = testImproved(expected, received);
112+
const statsBaseline = testBaseline(expected, received);
113+
writeRow('change', tenths * 10, statsImproved, statsBaseline);
114+
};
115+
116+
const getItems = (n, callback) => {
117+
const items = [];
118+
119+
for (let i = 0; i !== n; i += 1) {
120+
const item = callback(i);
121+
if (typeof item === 'string') {
122+
items.push(item);
123+
}
124+
}
125+
126+
return items.join('\n');
127+
};
128+
129+
// Simulate change of property name which is usually not same line.
130+
// Expected: 0 1 2 3 4 5 6 7 8 9 and so on
131+
// Received: 1 2 3 4 x0 5 6 7 8 9 and so on
132+
const change2 = i => {
133+
const j = i % 10;
134+
return j === 4 ? `x${i - 4}` : j < 4 ? `${i + 1}` : `${i}`;
135+
};
136+
137+
const testLength = n => {
138+
const all = getItems(n, i => `${i}`);
139+
140+
writeHeading3(n);
141+
142+
[2, 4, 8].forEach(tenth => {
143+
testDeleteInsert(tenth, all, getItems(n, i => i % 10 >= tenth && `${i}`));
144+
});
145+
testChange(1, all, getItems(n, i => (i % 10 === 0 ? `x${i}` : `${i}`)));
146+
testChange(2, all, getItems(n, change2));
147+
testChange(5, all, getItems(n, i => (i % 2 === 0 ? `x${i}` : `${i}`)));
148+
testChange(10, all, getItems(n, i => `x${i}`)); // simulate TDD
149+
};
150+
151+
writeHeading2();
152+
153+
testLength(20);
154+
testLength(200);
155+
testLength(2000);

‎yarn.lock

+18
Original file line numberDiff line numberDiff line change
@@ -2176,6 +2176,14 @@ beeper@^1.0.0:
21762176
resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809"
21772177
integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=
21782178

2179+
benchmark@^2.1.4:
2180+
version "2.1.4"
2181+
resolved "https://registry.yarnpkg.com/benchmark/-/benchmark-2.1.4.tgz#09f3de31c916425d498cc2ee565a0ebf3c2a5629"
2182+
integrity sha1-CfPeMckWQl1JjMLuVloOvzwqVik=
2183+
dependencies:
2184+
lodash "^4.17.4"
2185+
platform "^1.3.3"
2186+
21792187
better-assert@~1.0.0:
21802188
version "1.0.2"
21812189
resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522"
@@ -4091,6 +4099,11 @@ diff@3.5.0:
40914099
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
40924100
integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
40934101

4102+
diff@^4.0.1:
4103+
version "4.0.1"
4104+
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff"
4105+
integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==
4106+
40944107
diffie-hellman@^5.0.0:
40954108
version "5.0.3"
40964109
resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
@@ -9945,6 +9958,11 @@ pkg-dir@^3.0.0:
99459958
dependencies:
99469959
find-up "^3.0.0"
99479960

9961+
platform@^1.3.3:
9962+
version "1.3.5"
9963+
resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.5.tgz#fb6958c696e07e2918d2eeda0f0bc9448d733444"
9964+
integrity sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==
9965+
99489966
plist@2.0.1:
99499967
version "2.0.1"
99509968
resolved "https://registry.yarnpkg.com/plist/-/plist-2.0.1.tgz#0a32ca9481b1c364e92e18dc55c876de9d01da8b"

0 commit comments

Comments
 (0)
Please sign in to comment.