Skip to content

Commit

Permalink
refactor: custom tree comparer
Browse files Browse the repository at this point in the history
  • Loading branch information
mdjastrzebski committed Jun 1, 2024
1 parent f96ac6c commit e085e6c
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 31 deletions.
2 changes: 1 addition & 1 deletion packages/measure/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"dependencies": {
"@callstack/reassure-logger": "1.0.0-rc.4",
"mathjs": "^12.4.2",
"pretty-format": "^29.7.0"
"remeda": "^2.0.0"
},
"devDependencies": {
"@babel/core": "^7.24.5",
Expand Down
45 changes: 45 additions & 0 deletions packages/measure/src/__tests__/measure-renders.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,51 @@ test('measureRenders detects redundant updates', async () => {
expect(results.redundantRenders?.initial).toBe(0);
});

const AsyncMacroTaskEffect = () => {
const [count, setCount] = React.useState(0);

React.useEffect(() => {
setTimeout(() => setCount(1), 0);
}, []);

return (
<View>
<Text>Count: ${count}</Text>
</View>
);
};

test('ignores async macro-tasks effect', async () => {
const results = await measureRenders(<AsyncMacroTaskEffect />, { writeFile: false });
expect(results.redundantRenders?.initial).toBe(0);
expect(results.redundantRenders?.update).toBe(0);
});

const AsyncMicrotaskEffect = () => {
const [count, setCount] = React.useState(0);

React.useEffect(() => {
const asyncSet = async () => {
await Promise.resolve();
setCount(1);
};

void asyncSet();
}, []);

return (
<View>
<Text>Count: ${count}</Text>
</View>
);
};

test('ignores async micro-tasks effect', async () => {
const results = await measureRenders(<AsyncMicrotaskEffect />, { writeFile: false });
expect(results.redundantRenders?.initial).toBe(0);
expect(results.redundantRenders?.update).toBe(0);
});

function Wrapper({ children }: React.PropsWithChildren<{}>) {
return <View testID="wrapper">{children}</View>;
}
Expand Down
27 changes: 0 additions & 27 deletions packages/measure/src/measure-helpers.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
import * as math from 'mathjs';
import type { ReactTestRendererJSON } from 'react-test-renderer';
// eslint-disable-next-line import/no-extraneous-dependencies
import { format as prettyFormat, plugins as prettyFormatPlugins } from 'pretty-format';
import type { MeasureResults } from './types';

export interface RunResult {
duration: number;
count: number;
}

export type ToJsonTree = ReactTestRendererJSON | ReactTestRendererJSON[] | null;

export function processRunResults(inputResults: RunResult[], warmupRuns: number): MeasureResults {
const warmupResults = inputResults.slice(0, warmupRuns);
const results = inputResults.slice(warmupRuns);
Expand All @@ -35,25 +30,3 @@ export function processRunResults(inputResults: RunResult[], warmupRuns: number)
counts,
};
}

const { AsymmetricMatcher, DOMCollection, DOMElement, Immutable, ReactElement, ReactTestComponent } =
prettyFormatPlugins;
const PLUGINS = [ReactTestComponent, ReactElement, DOMElement, DOMCollection, Immutable, AsymmetricMatcher];
const FORMAT_OPTIONS = {
plugins: PLUGINS,
};

export function countRedundantUpdates(components: ToJsonTree[]): number {
const formatOptionsZeroIndent = { ...FORMAT_OPTIONS, indent: 0 };
let count = 0;

for (let i = 0; i < components.length - 1; i++) {
const aCompare = prettyFormat(components[i], formatOptionsZeroIndent);
const bCompare = prettyFormat(components[i + 1], formatOptionsZeroIndent);
if (aCompare === bCompare) {
count++;
}
}

return count;
}
24 changes: 22 additions & 2 deletions packages/measure/src/measure-renders.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as React from 'react';
import type { ReactTestRendererJSON, ReactTestRendererNode } from 'react-test-renderer';
import * as R from 'remeda';
import * as logger from '@callstack/reassure-logger';
import { config } from './config';
import { ToJsonTree, RunResult, processRunResults, countRedundantUpdates } from './measure-helpers';
import { RunResult, processRunResults } from './measure-helpers';
import { showFlagsOutputIfNeeded, writeTestStats } from './output';
import { resolveTestingLibrary, getTestingLibrary } from './testing-library';
import type { MeasureRendersResults } from './types';
Expand Down Expand Up @@ -117,7 +119,7 @@ async function measureRendersInternal(
...processRunResults(runResults, warmupRuns),
redundantRenders: {
initial: initialRenderTrees.length - 1,
update: countRedundantUpdates(regularRenderTrees),
update: detectRedundantUpdates(regularRenderTrees).length,
},
};
}
Expand All @@ -135,3 +137,21 @@ export function buildUiToRender(

return Wrapper ? <Wrapper>{uiWithProfiler}</Wrapper> : uiWithProfiler;
}

export type ToJsonTree = ReactTestRendererJSON | ReactTestRendererJSON[] | null;

export function isJsonTreeEqual(a: ToJsonTree | null, b: ToJsonTree | null): boolean {
return R.isDeepEqual(a, b);
}

export function detectRedundantUpdates(components: ToJsonTree[]): number[] {
const result = [];

for (let i = 1; i < components.length; i += 1) {
if (isJsonTreeEqual(components[i], components[i - 1])) {
result.push(i);
}
}

return result;
}
18 changes: 17 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2384,12 +2384,12 @@ __metadata:
jest: "npm:^29.7.0"
mathjs: "npm:^12.4.2"
prettier: "npm:^2.8.8"
pretty-format: "npm:^29.7.0"
react: "npm:18.2.0"
react-dom: "npm:18.2.0"
react-native: "npm:0.74.1"
react-native-builder-bob: "npm:^0.23.2"
react-test-renderer: "npm:18.2.0"
remeda: "npm:^2.0.0"
strip-ansi: "npm:^6.0.1"
typescript: "npm:^5.4.5"
peerDependencies:
Expand Down Expand Up @@ -11552,6 +11552,15 @@ __metadata:
languageName: node
linkType: hard

"remeda@npm:^2.0.0":
version: 2.0.0
resolution: "remeda@npm:2.0.0"
dependencies:
type-fest: "npm:^4.18.2"
checksum: 10c0/50262471a58e14c0873ddf029b32c633c994d8a8cdc3a15ecd9e4e09a02653226ab0c026ab60c7f4d1899062f89abacd01de0588562da4082996118c55c19695
languageName: node
linkType: hard

"repeat-string@npm:^1.0.0":
version: 1.6.1
resolution: "repeat-string@npm:1.6.1"
Expand Down Expand Up @@ -12973,6 +12982,13 @@ __metadata:
languageName: node
linkType: hard

"type-fest@npm:^4.18.2":
version: 4.18.3
resolution: "type-fest@npm:4.18.3"
checksum: 10c0/5d51a679a86548e8c35008f09dc8f9f8fdb0fcc79c30d116c9e6c5459a450db28a7e6e6887e6a8a6a560d2cde3757347a5984c18b871de6e739a63991ce2d8d9
languageName: node
linkType: hard

"typed-array-buffer@npm:^1.0.1, typed-array-buffer@npm:^1.0.2":
version: 1.0.2
resolution: "typed-array-buffer@npm:1.0.2"
Expand Down

0 comments on commit e085e6c

Please sign in to comment.