From 4a673eb437e07a339cdd0bc37f7e7452f9868cfc Mon Sep 17 00:00:00 2001 From: Maciej Jastrzebski Date: Sun, 16 Jun 2024 18:11:33 +0200 Subject: [PATCH 1/4] feat: display warmup runs and render issues with markdown report details --- packages/compare/src/index.ts | 1 + packages/compare/src/output/markdown.ts | 30 ++++++++++++++++++++++--- packages/compare/src/type-schemas.ts | 12 +++++----- packages/compare/src/types.ts | 3 ++- packages/reassure/src/index.ts | 1 + 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/packages/compare/src/index.ts b/packages/compare/src/index.ts index 8c03af5a..e8e29eac 100644 --- a/packages/compare/src/index.ts +++ b/packages/compare/src/index.ts @@ -10,4 +10,5 @@ export type { CompareEntry, AddedEntry, RemovedEntry, + RenderIssue, } from './types'; diff --git a/packages/compare/src/output/markdown.ts b/packages/compare/src/output/markdown.ts index f2be3be5..8417ac59 100644 --- a/packages/compare/src/output/markdown.ts +++ b/packages/compare/src/output/markdown.ts @@ -12,7 +12,15 @@ import { formatDurationChange, } from '../utils/format'; import * as md from '../utils/markdown'; -import type { AddedEntry, CompareEntry, CompareResult, RemovedEntry, MeasureEntry, MeasureMetadata } from '../types'; +import type { + AddedEntry, + CompareEntry, + CompareResult, + RemovedEntry, + MeasureEntry, + MeasureMetadata, + RenderIssue, +} from '../types'; import { collapsibleSection } from '../utils/markdown'; const tableHeader = ['Name', 'Type', 'Duration', 'Count'] as const; @@ -76,7 +84,7 @@ function buildMarkdown(data: CompareResult) { result += `\n${buildSummaryTable(data.countChanged)}`; result += `\n${buildDetailsTable(data.countChanged)}`; result += `\n\n${md.heading3('Render Issues')}`; - result += `\n${buildRedundantRendersTable(data.renderIssues)}`; + result += `\n${buildRenderIssuesTable(data.renderIssues)}`; } result += `\n\n${md.heading3('Added Scenarios')}`; @@ -158,6 +166,7 @@ function buildDurationDetails(title: string, entry: MeasureEntry) { `Mean: ${formatDuration(entry.meanDuration)}`, `Stdev: ${formatDuration(entry.stdevDuration)} (${formatPercent(relativeStdev)})`, entry.durations ? `Runs: ${formatRunDurations(entry.durations)}` : '', + entry.warmupDurations ? `Warmup: ${formatRunDurations(entry.warmupDurations)}` : '', ] .filter(Boolean) .join(`
`); @@ -171,6 +180,7 @@ function buildCountDetails(title: string, entry: MeasureEntry) { `Mean: ${formatCount(entry.meanCount)}`, `Stdev: ${formatCount(entry.stdevCount)} (${formatPercent(relativeStdev)})`, entry.counts ? `Runs: ${entry.counts.map(formatCount).join(' ')}` : '', + buildRenderIssuesList(entry.issues), ] .filter(Boolean) .join(`
`); @@ -180,7 +190,7 @@ function formatRunDurations(values: number[]) { return values.map((v) => (Number.isInteger(v) ? `${v}` : `${v.toFixed(1)}`)).join(' '); } -function buildRedundantRendersTable(entries: Array) { +function buildRenderIssuesTable(entries: Array) { if (!entries.length) return md.italic('There are no entries'); const tableHeader = ['Name', 'Initial Updates', 'Redundant Updates'] as const; @@ -193,6 +203,20 @@ function buildRedundantRendersTable(entries: Array) { return markdownTable([tableHeader, ...rows]); } +function buildRenderIssuesList(issues: RenderIssue | undefined) { + if (issues == null) return ''; + + const output = []; + if (issues?.initialUpdateCount) { + output.push(`* Initial updates: ${formatInitialUpdates(issues.initialUpdateCount)}`); + } + if (issues?.redundantUpdates) { + output.push(`* Redundant updates: ${formatRedundantUpdates(issues.redundantUpdates)}`); + } + + return output.join('\n'); +} + function formatInitialUpdates(count: number | undefined) { if (count == null) return '?'; if (count === 0) return '-'; diff --git a/packages/compare/src/type-schemas.ts b/packages/compare/src/type-schemas.ts index b0dead0e..6f35a1ce 100644 --- a/packages/compare/src/type-schemas.ts +++ b/packages/compare/src/type-schemas.ts @@ -12,6 +12,11 @@ export const MeasureHeaderScheme = z.object({ metadata: MeasureMetadataScheme, }); +export const RenderIssueScheme = z.object({ + initialUpdateCount: z.number().optional(), + redundantUpdates: z.array(z.number()).optional(), +}); + /** Entry in the performance results file. */ export const MeasureEntryScheme = z.object({ /** Name of the test scenario. */ @@ -44,10 +49,5 @@ export const MeasureEntryScheme = z.object({ /** Array of measured render/execution counts for each run. */ counts: z.array(z.number()), - issues: z.optional( - z.object({ - initialUpdateCount: z.number().optional(), - redundantUpdates: z.array(z.number()).optional(), - }) - ), + issues: z.optional(RenderIssueScheme), }); diff --git a/packages/compare/src/types.ts b/packages/compare/src/types.ts index 0d9ab976..df2ee535 100644 --- a/packages/compare/src/types.ts +++ b/packages/compare/src/types.ts @@ -1,10 +1,11 @@ /** Parsed performance results file. */ import type { z } from 'zod'; -import type { MeasureEntryScheme, MeasureHeaderScheme, MeasureMetadataScheme } from './type-schemas'; +import type { MeasureEntryScheme, MeasureHeaderScheme, MeasureMetadataScheme, RenderIssueScheme } from './type-schemas'; export type MeasureHeader = z.infer; export type MeasureMetadata = z.infer; export type MeasureEntry = z.infer; +export type RenderIssue = z.infer; export type MeasureType = MeasureEntry['type']; export interface MeasureResults { diff --git a/packages/reassure/src/index.ts b/packages/reassure/src/index.ts index 97c84f14..e457a29c 100644 --- a/packages/reassure/src/index.ts +++ b/packages/reassure/src/index.ts @@ -22,4 +22,5 @@ export type { CompareEntry, AddedEntry, RemovedEntry, + RenderIssues, } from '@callstack/reassure-compare'; From 2c458acfba9e7e5a1f0113b34818fdbd130bd7ca Mon Sep 17 00:00:00 2001 From: Maciej Jastrzebski Date: Sun, 16 Jun 2024 18:12:51 +0200 Subject: [PATCH 2/4] refactor: fix typing --- packages/compare/src/index.ts | 2 +- packages/compare/src/output/markdown.ts | 4 ++-- packages/compare/src/type-schemas.ts | 4 ++-- packages/compare/src/types.ts | 9 +++++++-- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/compare/src/index.ts b/packages/compare/src/index.ts index e8e29eac..fcd03513 100644 --- a/packages/compare/src/index.ts +++ b/packages/compare/src/index.ts @@ -10,5 +10,5 @@ export type { CompareEntry, AddedEntry, RemovedEntry, - RenderIssue, + RenderIssues, } from './types'; diff --git a/packages/compare/src/output/markdown.ts b/packages/compare/src/output/markdown.ts index 8417ac59..72175f05 100644 --- a/packages/compare/src/output/markdown.ts +++ b/packages/compare/src/output/markdown.ts @@ -19,7 +19,7 @@ import type { RemovedEntry, MeasureEntry, MeasureMetadata, - RenderIssue, + RenderIssues, } from '../types'; import { collapsibleSection } from '../utils/markdown'; @@ -203,7 +203,7 @@ function buildRenderIssuesTable(entries: Array) { return markdownTable([tableHeader, ...rows]); } -function buildRenderIssuesList(issues: RenderIssue | undefined) { +function buildRenderIssuesList(issues: RenderIssues | undefined) { if (issues == null) return ''; const output = []; diff --git a/packages/compare/src/type-schemas.ts b/packages/compare/src/type-schemas.ts index 6f35a1ce..be5a34a4 100644 --- a/packages/compare/src/type-schemas.ts +++ b/packages/compare/src/type-schemas.ts @@ -12,7 +12,7 @@ export const MeasureHeaderScheme = z.object({ metadata: MeasureMetadataScheme, }); -export const RenderIssueScheme = z.object({ +export const RenderIssuesScheme = z.object({ initialUpdateCount: z.number().optional(), redundantUpdates: z.array(z.number()).optional(), }); @@ -49,5 +49,5 @@ export const MeasureEntryScheme = z.object({ /** Array of measured render/execution counts for each run. */ counts: z.array(z.number()), - issues: z.optional(RenderIssueScheme), + issues: z.optional(RenderIssuesScheme), }); diff --git a/packages/compare/src/types.ts b/packages/compare/src/types.ts index df2ee535..38eb7acc 100644 --- a/packages/compare/src/types.ts +++ b/packages/compare/src/types.ts @@ -1,11 +1,16 @@ /** Parsed performance results file. */ import type { z } from 'zod'; -import type { MeasureEntryScheme, MeasureHeaderScheme, MeasureMetadataScheme, RenderIssueScheme } from './type-schemas'; +import type { + MeasureEntryScheme, + MeasureHeaderScheme, + MeasureMetadataScheme, + RenderIssuesScheme, +} from './type-schemas'; export type MeasureHeader = z.infer; export type MeasureMetadata = z.infer; export type MeasureEntry = z.infer; -export type RenderIssue = z.infer; +export type RenderIssues = z.infer; export type MeasureType = MeasureEntry['type']; export interface MeasureResults { From e58eface803bdc6089d5a7aee0a5deeb074c5848 Mon Sep 17 00:00:00 2001 From: Maciej Jastrzebski Date: Sun, 16 Jun 2024 18:17:53 +0200 Subject: [PATCH 3/4] refactor: tweaks --- .changeset/ten-toes-turn.md | 6 ++++++ packages/compare/src/output/markdown.ts | 10 +++++----- 2 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 .changeset/ten-toes-turn.md diff --git a/.changeset/ten-toes-turn.md b/.changeset/ten-toes-turn.md new file mode 100644 index 00000000..40868427 --- /dev/null +++ b/.changeset/ten-toes-turn.md @@ -0,0 +1,6 @@ +--- +'reassure': minor +'@callstack/reassure-compare': minor +--- + +Expose "Warmup Runs" and "Render Issues" in markdown report diff --git a/packages/compare/src/output/markdown.ts b/packages/compare/src/output/markdown.ts index 72175f05..81872688 100644 --- a/packages/compare/src/output/markdown.ts +++ b/packages/compare/src/output/markdown.ts @@ -166,7 +166,7 @@ function buildDurationDetails(title: string, entry: MeasureEntry) { `Mean: ${formatDuration(entry.meanDuration)}`, `Stdev: ${formatDuration(entry.stdevDuration)} (${formatPercent(relativeStdev)})`, entry.durations ? `Runs: ${formatRunDurations(entry.durations)}` : '', - entry.warmupDurations ? `Warmup: ${formatRunDurations(entry.warmupDurations)}` : '', + entry.warmupDurations ? `Warmup runs: ${formatRunDurations(entry.warmupDurations)}` : '', ] .filter(Boolean) .join(`
`); @@ -206,15 +206,15 @@ function buildRenderIssuesTable(entries: Array) { function buildRenderIssuesList(issues: RenderIssues | undefined) { if (issues == null) return ''; - const output = []; + const output = ['Render issues:']; if (issues?.initialUpdateCount) { - output.push(`* Initial updates: ${formatInitialUpdates(issues.initialUpdateCount)}`); + output.push(` - Initial updates: ${formatInitialUpdates(issues.initialUpdateCount)}`); } if (issues?.redundantUpdates) { - output.push(`* Redundant updates: ${formatRedundantUpdates(issues.redundantUpdates)}`); + output.push(` - Redundant updates: ${formatRedundantUpdates(issues.redundantUpdates)}`); } - return output.join('\n'); + return output.join('
'); } function formatInitialUpdates(count: number | undefined) { From d6676dde43155482b7625b3ecfe41bf3a79cfcd6 Mon Sep 17 00:00:00 2001 From: Maciej Jastrzebski Date: Sun, 16 Jun 2024 18:25:27 +0200 Subject: [PATCH 4/4] refactor: tweaks output --- packages/compare/src/output/markdown.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/compare/src/output/markdown.ts b/packages/compare/src/output/markdown.ts index 81872688..8b85e1cf 100644 --- a/packages/compare/src/output/markdown.ts +++ b/packages/compare/src/output/markdown.ts @@ -208,25 +208,25 @@ function buildRenderIssuesList(issues: RenderIssues | undefined) { const output = ['Render issues:']; if (issues?.initialUpdateCount) { - output.push(` - Initial updates: ${formatInitialUpdates(issues.initialUpdateCount)}`); + output.push(` - Initial updates: ${formatInitialUpdates(issues.initialUpdateCount, false)}`); } - if (issues?.redundantUpdates) { - output.push(` - Redundant updates: ${formatRedundantUpdates(issues.redundantUpdates)}`); + if (issues?.redundantUpdates?.length) { + output.push(` - Redundant updates: ${formatRedundantUpdates(issues.redundantUpdates, false)}`); } return output.join('
'); } -function formatInitialUpdates(count: number | undefined) { +function formatInitialUpdates(count: number | undefined, showSymbol: boolean = true) { if (count == null) return '?'; if (count === 0) return '-'; - return `${count} 🔴`; + return `${count}${showSymbol ? ' 🔴' : ''}`; } -function formatRedundantUpdates(redundantUpdates: number[] | undefined) { +function formatRedundantUpdates(redundantUpdates: number[] | undefined, showSymbol: boolean = true) { if (redundantUpdates == null) return '?'; if (redundantUpdates.length === 0) return '-'; - return `${redundantUpdates.length} (${redundantUpdates.join(', ')}) 🔴`; + return `${redundantUpdates.length} (${redundantUpdates.join(', ')})${showSymbol ? ' 🔴' : ''}`; }