Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ flowchart LR

### Framework Configuration

- [`frameworks.ts`](./packages/results/src/frameworks.ts) selects which measurements run for each starter and app.
- Put benchmark settings in [`measurements.ts`](./packages/results/src/measurements.ts). For example, `install: { runs: 5 }` runs five install measurements per job for each enabled starter. Entries like `dependencies: {}` have no configurable repeat count here.
- [`frameworks-config.ts`](./packages/results/src/frameworks-config.ts) selects which measurements run for each starter and app.
- Put benchmark settings in [`measurements-config.ts`](./packages/results/src/measurements-config.ts). For example, `install: { runs: 5 }` runs five install measurements per job for each enabled starter. Entries like `dependencies: null` have no configurable repeat count here.

Edit the TypeScript config. [`print-frameworks.ts`](./packages/stats-generator/src/print-frameworks.ts)
prints it as JSON so CI can build its benchmark matrices. Astro imports the same
Expand Down Expand Up @@ -227,7 +227,7 @@ If approved, follow these steps:

2. **Create the app package** (optional): If runtime performance testing is planned, add an `app-*` package (e.g., `packages/app-my-framework`) with a more complex setup that includes features like dynamic routing or client-side interactivity. Make sure the framework dependency is pinned to the same exact version as the starter package.

3. **Add an entry to `packages/results/src/frameworks.ts`** using the same format as the framework configuration example above.
3. **Add an entry to `packages/results/src/frameworks-config.ts`** using the same format as the framework configuration example above.

```ts
{
Expand All @@ -247,7 +247,7 @@ If approved, follow these steps:

5. **Test locally**: Make sure the framework builds successfully by running the build script from inside the package directory.

6. CI for `sync-version` and `generate-stats` will automatically pick up the new framework from `packages/results/src/frameworks.ts`. The Benchmarks workflow runs the same measurements and validates their outputs on pull requests and on `main`; only runs on `main` save the results and create a stats update PR.
6. CI for `sync-version` and `generate-stats` will automatically pick up the new framework from `packages/results/src/frameworks-config.ts`. The Benchmarks workflow runs the same measurements and validates their outputs on pull requests and on `main`; only runs on `main` save the results and create a stats update PR.

7. **Submit a PR**: Open a pull request with the new packages, configuration, and methodology updates. Once merged, the CI will automatically pick up the new framework and raise a PR with new metrics.

Expand Down
4 changes: 2 additions & 2 deletions packages/docs/src/content.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { file, glob } from 'astro/loaders'
import { docsLoader } from '@astrojs/starlight/loaders'
import { docsSchema } from '@astrojs/starlight/schema'
import { z } from 'astro/zod'
import { frameworks } from '@framework-performance/results/frameworks'
import { frameworksConfig } from '@framework-performance/results/frameworks-config'

const cwvCollection = defineCollection({
loader: file('src/content/cwv/cwv-stats.json'),
Expand Down Expand Up @@ -40,7 +40,7 @@ const cwvCollection = defineCollection({
})

const frameworkSlugs = new Set(
frameworks.flatMap((framework) =>
frameworksConfig.flatMap((framework) =>
framework.starter
? [framework.starter.package.replace(/^starter-/, '')]
: [],
Expand Down
6 changes: 3 additions & 3 deletions packages/docs/src/lib/framework-logos.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { frameworks } from '@framework-performance/results/frameworks'
import { frameworksConfig } from '@framework-performance/results/frameworks-config'

export type ThemedValue = { dark: string; light?: string }
export type FrameworkLogo = ThemedValue
Expand Down Expand Up @@ -58,14 +58,14 @@ export const frameworkBrands: Record<string, FrameworkBrand> = {
}

const brandKeyByDisplayName = new Map<string, string>([
...frameworks.map((f) => [f.displayName, f.name] as const),
...frameworksConfig.map((f) => [f.displayName, f.name] as const),
['Nuxt.js', 'nuxt'],
['Gatsby', 'gatsby'],
['WordPress', 'wordpress'],
])

const brandKeyByPackage = new Map<string, string>(
frameworks.flatMap((f) =>
frameworksConfig.flatMap((f) =>
[f.starter?.package, f.app?.package].flatMap((packageName) =>
packageName ? [[packageName, f.name] as const] : [],
),
Expand Down
4 changes: 0 additions & 4 deletions packages/docs/src/lib/interaction-history.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ test('rendered tests take interaction phases from the run with the median total'
firstPaint: metric(100),
firstContentfulPaint: metric(100),
interactionTests: {
scenario: 'first-row-detail-navigation',
source: 'lighthouse-inp-breakdown',
interactionLatency: metric(30),
inputDelay: metric(2),
processingDuration: metric(20),
Expand All @@ -67,8 +65,6 @@ test('rendered tests take interaction phases from the run with the median total'
})

assert.deepEqual(formatted.interactionTests, {
scenario: 'first-row-detail-navigation',
source: 'lighthouse-inp-breakdown',
...timings(1, 20, 9),
})
})
Expand Down
6 changes: 3 additions & 3 deletions packages/docs/src/lib/prepare-chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { INTERACTION_PHASES } from './interaction-phases'
import { stackGrays } from './chart-styles'
import { prepareInitialLoadResources } from './initial-load'
import { getCollection } from 'astro:content'
import { frameworks } from '@framework-performance/results/frameworks'
import { frameworksConfig } from '@framework-performance/results/frameworks-config'
export * from './chart-measurements'
import type { CombinedResult } from '@framework-performance/results/storage'
import { prepareRuntimeResult, prepareStarterResult } from './result-content'
Expand All @@ -17,8 +17,8 @@ const latest = Object.entries(resultFiles)
.map(([, result]) => result)
.sort(
(a, b) =>
frameworks.findIndex((f) => f.name === a.framework) -
frameworks.findIndex((f) => f.name === b.framework),
frameworksConfig.findIndex((f) => f.name === a.framework) -
frameworksConfig.findIndex((f) => f.name === b.framework),
)
const history = Object.entries(resultFiles)
.filter(([path]) => path.includes('/versions/'))
Expand Down
8 changes: 4 additions & 4 deletions packages/docs/src/lib/prepare-table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type {
} from './types'
import { prepareInitialLoadResources } from './initial-load'
import { formatChartValue } from './chart'
import { frameworks } from '@framework-performance/results/frameworks'
import { frameworksConfig } from '@framework-performance/results/frameworks-config'
import { getCollection } from 'astro:content'
import { formatBytesToMB, formatTimeMs, getFrameworkSlug } from './utils'

Expand All @@ -18,8 +18,8 @@ const resultFiles = import.meta.glob<CombinedResult>(
)
const results = Object.values(resultFiles).sort(
(a, b) =>
frameworks.findIndex((f) => f.name === a.framework) -
frameworks.findIndex((f) => f.name === b.framework),
frameworksConfig.findIndex((f) => f.name === a.framework) -
frameworksConfig.findIndex((f) => f.name === b.framework),
)
const starterStats = results
.filter((result) => result.projects.starter)
Expand Down Expand Up @@ -378,7 +378,7 @@ type LatencyTableInput = {
valueFormat: ChartValueFormat
}
const frameworkDefinition = (name: string) =>
frameworks.find((f) => f.displayName === name || f.name === name)
frameworksConfig.find((f) => f.displayName === name || f.name === name)
function frameworkColumn(): TableColumn {
return {
key: 'name',
Expand Down
6 changes: 0 additions & 6 deletions packages/docs/src/lib/request-throughput.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,6 @@ const benchmark = {
totalRequests: { value: 9, unit: 'requests' },
bodySize: { value: 20.5, unit: 'KiB' },
duplicationFactor: { value: 1.25, unit: 'ratio' },
durationMs: 10_000,
warmupDurationMs: 250,
minimumRequests: 64,
warmupMinimumRequests: 16,
source: 'tinybench',
path: '/ssr-throughput',
} satisfies NonNullable<FrameworkResult['ssrRequestThroughput']>

test('throughput charts use the median of run means, not the mean or request median', () => {
Expand Down
6 changes: 3 additions & 3 deletions packages/docs/src/lib/result-content.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getLoadPeakStage } from '@framework-performance/results/selection'
import type { CombinedResult } from '@framework-performance/results/storage'
import { frameworks } from '@framework-performance/results/frameworks'
import { frameworksConfig } from '@framework-performance/results/frameworks-config'
import type {
FrameworkResult,
InteractionTimingSchema,
Expand Down Expand Up @@ -130,7 +130,7 @@ function formatLoad(value: NonNullable<FrameworkResult['ssrLoad']>) {
}

export function prepareRuntimeResult(result: CombinedResult) {
const framework = frameworks.find((f) => f.name === result.framework)!
const framework = frameworksConfig.find((f) => f.name === result.framework)!
const value = {
...result.projects.app,
name: framework.displayName,
Expand Down Expand Up @@ -190,7 +190,7 @@ export function prepareRuntimeResult(result: CombinedResult) {
}
}
export function prepareStarterResult(result: CombinedResult) {
const framework = frameworks.find((f) => f.name === result.framework)!
const framework = frameworksConfig.find((f) => f.name === result.framework)!
return {
...result.projects.starter,
name: framework.displayName,
Expand Down
57 changes: 35 additions & 22 deletions packages/results/data/astro/latest.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@
"project": "app",
"result": {
"name": "initialLoad",
"source": "lighthouse-resource-summary",
"path": "/initial-load",
"resources": {
"total": {
"requestCount": {
Expand Down Expand Up @@ -578,13 +576,7 @@
"duplicationFactor": {
"value": 1,
"unit": "ratio"
},
"durationMs": 10000,
"warmupDurationMs": 250,
"minimumRequests": 64,
"warmupMinimumRequests": 16,
"source": "tinybench",
"path": "/ssr-throughput"
}
}
},
"ssrLoad": {
Expand Down Expand Up @@ -1587,16 +1579,7 @@
}
]
],
"configuration": {
"stageConnections": [1, 5, 10, 25, 50, 100, 200],
"warmupDurationMs": 5000,
"recoveryMs": 5000,
"warmupAttempts": 3,
"stageDurationMs": 5000
},
"representativeIterationIndex": 2,
"source": "autocannon",
"path": "/server-side-rendered",
"totalRequests": {
"value": 139712,
"unit": "requests"
Expand Down Expand Up @@ -3648,8 +3631,6 @@
}
},
"interactionTests": {
"scenario": "first-row-detail-navigation",
"source": "lighthouse-inp-breakdown",
"interactionLatency": {
"unit": "ms",
"mean": 2.2696000000000005,
Expand Down Expand Up @@ -3957,8 +3938,6 @@
}
},
"interactionTests": {
"scenario": "first-row-detail-navigation",
"source": "lighthouse-inp-breakdown",
"interactionLatency": {
"unit": "ms",
"mean": 0.9266,
Expand Down Expand Up @@ -4227,5 +4206,39 @@
"project": "starter",
"result": ["@astrojs/prism", "@astrojs/telemetry", "astro"]
}
},
"configuration": {
"install": { "runs": 5 },
"build": { "runs": 5 },
"devServer": { "runs": 5 },
"dependencies": null,
"browserBaseline": null,
"nodeEngines": null,
"ssrRequestThroughput": {
"runs": 5,
"durationMs": 10000,
"warmupDurationMs": 250,
"minimumRequests": 64,
"warmupMinimumRequests": 16,
"path": "/ssr-throughput"
},
"ssrLoad": {
"runs": 3,
"stageConnections": [1, 5, 10, 25, 50, 100, 200],
"stageDurationMs": 5000,
"warmupDurationMs": 5000,
"warmupAttempts": 3,
"recoveryMs": 5000,
"path": "/server-side-rendered"
},
"clientSideRendered": {
"runs": 5,
"scenario": "first-row-detail-navigation"
},
"serverSideRendered": {
"runs": 5,
"scenario": "first-row-detail-navigation"
},
"initialLoad": { "path": "/initial-load" }
}
}
31 changes: 21 additions & 10 deletions packages/results/data/astro/versions/7.1.6.json
Original file line number Diff line number Diff line change
Expand Up @@ -429,13 +429,7 @@
}
]
],
"configuration": {
"stageConnections": [1, 5, 10, 25, 50, 100, 200],
"warmupDurationMs": 5000
},
"representativeIterationIndex": 1,
"source": "autocannon",
"path": "/server-side-rendered",
"totalRequests": { "value": 110475, "unit": "requests" },
"totalErrors": { "value": 0, "unit": "errors" },
"stage1": {
Expand Down Expand Up @@ -1016,8 +1010,6 @@
"max": 129.087
},
"interactionTests": {
"scenario": "first-row-detail-navigation",
"source": "lighthouse-inp-breakdown",
"interactionLatency": {
"unit": "ms",
"mean": 1.63925,
Expand Down Expand Up @@ -1111,8 +1103,6 @@
"max": 71.557
},
"interactionTests": {
"scenario": "first-row-detail-navigation",
"source": "lighthouse-inp-breakdown",
"interactionLatency": {
"unit": "ms",
"mean": 1.5494999999999999,
Expand Down Expand Up @@ -1205,5 +1195,26 @@
"project": "starter",
"result": { "value": 2117, "unit": "ms" }
}
},
"configuration": {
"install": { "runs": 5 },
"build": { "runs": 5 },
"devServer": { "runs": 5 },
"dependencies": null,
"browserBaseline": null,
"ssrLoad": {
"runs": 3,
"stageConnections": [1, 5, 10, 25, 50, 100, 200],
"warmupDurationMs": 5000,
"path": "/server-side-rendered"
},
"clientSideRendered": {
"runs": 4,
"scenario": "first-row-detail-navigation"
},
"serverSideRendered": {
"runs": 4,
"scenario": "first-row-detail-navigation"
}
}
}
31 changes: 21 additions & 10 deletions packages/results/data/astro/versions/7.2.10.json
Original file line number Diff line number Diff line change
Expand Up @@ -429,13 +429,7 @@
}
]
],
"configuration": {
"stageConnections": [1, 5, 10, 25, 50, 100, 200],
"warmupDurationMs": 5000
},
"representativeIterationIndex": 1,
"source": "autocannon",
"path": "/server-side-rendered",
"totalRequests": { "value": 110570, "unit": "requests" },
"totalErrors": { "value": 0, "unit": "errors" },
"stage1": {
Expand Down Expand Up @@ -1013,8 +1007,6 @@
"max": 111.698
},
"interactionTests": {
"scenario": "first-row-detail-navigation",
"source": "lighthouse-inp-breakdown",
"interactionLatency": {
"unit": "ms",
"mean": 1.935,
Expand Down Expand Up @@ -1108,8 +1100,6 @@
"max": 67.055
},
"interactionTests": {
"scenario": "first-row-detail-navigation",
"source": "lighthouse-inp-breakdown",
"interactionLatency": {
"unit": "ms",
"mean": 4.912,
Expand Down Expand Up @@ -1205,5 +1195,26 @@
"project": "starter",
"result": { "value": 2117, "unit": "ms" }
}
},
"configuration": {
"install": { "runs": 5 },
"build": { "runs": 5 },
"devServer": { "runs": 5 },
"dependencies": null,
"browserBaseline": null,
"ssrLoad": {
"runs": 3,
"stageConnections": [1, 5, 10, 25, 50, 100, 200],
"warmupDurationMs": 5000,
"path": "/server-side-rendered"
},
"clientSideRendered": {
"runs": 4,
"scenario": "first-row-detail-navigation"
},
"serverSideRendered": {
"runs": 4,
"scenario": "first-row-detail-navigation"
}
}
}
Loading
Loading