Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expand performance tests setup #6515

Closed
Closed
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
900cad1
Run performance tests on Multisite
swissspidy May 7, 2024
c95cda2
Collect object cache stats
swissspidy May 7, 2024
1c18e90
Add same server-timings in admin
swissspidy May 7, 2024
fb028c6
Fix artifact name
swissspidy May 7, 2024
b69b2f8
Add safeguard
swissspidy May 7, 2024
e34fc08
Fix indentation
swissspidy May 7, 2024
2fee620
Enable themes on Multisite
swissspidy May 7, 2024
36455dd
Merge branch 'trunk' into try/performance-tests-expand
swissspidy Dec 17, 2024
728913e
Clear cache with a helper plugin
swissspidy Dec 17, 2024
69849bc
Test single posts as well
swissspidy Dec 17, 2024
ad658cd
Merge branch 'trunk' into try/performance-tests-expand
swissspidy Dec 17, 2024
4d5d7e0
Reference workflow from fork
swissspidy Dec 17, 2024
f7384a0
Import required fixture
swissspidy Dec 17, 2024
b543497
Use correct variable
swissspidy Dec 17, 2024
a900631
Update `testSuiteMap`
swissspidy Dec 17, 2024
8273372
Merge branch 'trunk' into try/performance-tests-expand
swissspidy Dec 17, 2024
75b5545
Merge branch 'trunk' into try/performance-tests-expand
swissspidy Dec 18, 2024
ded1aab
Use slash
swissspidy Dec 18, 2024
0816902
Remove cache hits/misses info again
swissspidy Dec 18, 2024
4afb18c
Try a `<details>`
swissspidy Dec 18, 2024
ef2462d
Try different title
swissspidy Dec 18, 2024
dbda9c1
Add comments
swissspidy Dec 18, 2024
e47a42e
Move constants to utils
swissspidy Dec 18, 2024
4738894
no export
swissspidy Dec 18, 2024
f91e385
Change name
swissspidy Dec 18, 2024
3257192
Use html markup
swissspidy Dec 18, 2024
2014ca3
Revert name change
swissspidy Dec 18, 2024
8feb4ff
Shorter names
swissspidy Dec 18, 2024
1f3030d
Longer again
swissspidy Dec 18, 2024
668dd47
Undo location change
swissspidy Dec 19, 2024
1a7cd79
Try name the other way around
swissspidy Dec 19, 2024
04e894c
Back on square 1
swissspidy Dec 19, 2024
05cd6a2
Try suggestion
swissspidy Dec 19, 2024
db424c4
Merge branch 'trunk' into try/performance-tests-expand
swissspidy Dec 19, 2024
b337a57
Alternative
swissspidy Dec 19, 2024
daf70f0
alt
swissspidy Dec 19, 2024
eb88943
Remove second half
swissspidy Dec 19, 2024
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
6 changes: 4 additions & 2 deletions .github/workflows/performance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,19 @@ permissions: {}
jobs:
# Runs the performance test suite.
performance:
name: Performance tests ${{ matrix.memcached && '(with memcached)' || '' }}
uses: WordPress/wordpress-develop/.github/workflows/reusable-performance.yml@trunk
name: ${{ matrix.multisite && 'Multisite' || 'Single' }}${{ matrix.memcached && ' (memcached)' || '' }}
swissspidy marked this conversation as resolved.
Show resolved Hide resolved
uses: swissspidy/wordpress-develop/.github/workflows/reusable-performance.yml@try/performance-tests-expand
swissspidy marked this conversation as resolved.
Show resolved Hide resolved
permissions:
contents: read
if: ${{ ( github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' ) }}
strategy:
fail-fast: false
matrix:
memcached: [ true, false ]
multisite: [ true, false ]
with:
memcached: ${{ matrix.memcached }}
multisite: ${{ matrix.multisite }}
secrets:
CODEVITALS_PROJECT_TOKEN: ${{ secrets.CODEVITALS_PROJECT_TOKEN }}

Expand Down
36 changes: 26 additions & 10 deletions .github/workflows/reusable-performance.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
##
# A reusable workflow that runs the performance test suite.
##
name: Performance Tests
name: Run performance Tests

on:
workflow_call:
Expand All @@ -26,6 +26,11 @@ on:
required: false
type: 'boolean'
default: false
multisite:
description: 'Whether to use Multisite.'
required: false
type: 'boolean'
default: false
secrets:
CODEVITALS_PROJECT_TOKEN:
description: 'The authorization token for https://www.codevitals.run/project/wordpress.'
Expand Down Expand Up @@ -53,6 +58,7 @@ env:

LOCAL_PHP_MEMCACHED: ${{ inputs.memcached }}
LOCAL_PHP: ${{ inputs.php-version }}${{ 'latest' != inputs.php-version && '-fpm' || '' }}
LOCAL_MULTISITE: ${{ inputs.multisite }}

jobs:
# Performs the following steps:
Expand All @@ -67,7 +73,9 @@ jobs:
# - Start Docker environment.
# - Log running Docker containers.
# - Docker debug information.
# - Install object cache drop-in.
# - Install WordPress.
# - Enable themes on Multisite.
# - Install WordPress Importer plugin.
# - Import mock data.
# - Deactivate WordPress Importer plugin.
Expand Down Expand Up @@ -98,7 +106,7 @@ jobs:
# - Publish performance results.
# - Ensure version-controlled files are not modified or deleted.
performance:
name: Run tests
name: Performance tests / ${{ inputs.multisite && 'Multisite' || 'Single' }}${{ inputs.memcached && ' (memcached)' || '' }}
runs-on: ubuntu-latest
permissions:
contents: read
Expand Down Expand Up @@ -147,10 +155,6 @@ jobs:
- name: Start Docker environment
run: npm run env:start

- name: Install object cache drop-in
if: ${{ inputs.memcached }}
run: cp src/wp-content/object-cache.php build/wp-content/object-cache.php

- name: Log running Docker containers
run: docker ps -a

Expand All @@ -163,9 +167,21 @@ jobs:
docker compose run --rm php php -i
docker compose run --rm php locale -a

- name: Install object cache drop-in
if: ${{ inputs.memcached }}
run: cp src/wp-content/object-cache.php build/wp-content/object-cache.php
swissspidy marked this conversation as resolved.
Show resolved Hide resolved

- name: Install WordPress
run: npm run env:install

- name: Enable themes on Multisite
if: ${{ inputs.multisite }}
run: |
npm run env:cli -- theme enable twentytwentyone --network --path=/var/www/${{ env.LOCAL_DIR }}
npm run env:cli -- theme enable twentytwentythree --network --path=/var/www/${{ env.LOCAL_DIR }}
npm run env:cli -- theme enable twentytwentyfour --network --path=/var/www/${{ env.LOCAL_DIR }}
npm run env:cli -- theme enable twentytwentyfive --network --path=/var/www/${{ env.LOCAL_DIR }}
swissspidy marked this conversation as resolved.
Show resolved Hide resolved

- name: Install WordPress Importer plugin
run: npm run env:cli -- plugin install wordpress-importer --activate --path=/var/www/${{ env.LOCAL_DIR }}

Expand Down Expand Up @@ -290,7 +306,7 @@ jobs:
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
if: always()
with:
name: performance-artifacts${{ inputs.memcached && '-memcached' || '' }}-${{ github.run_id }}
name: performance-artifacts${{ inputs.multisite && '-multisite' || '' }}${{ inputs.memcached && '-memcached' || '' }}-${{ github.run_id }}
swissspidy marked this conversation as resolved.
Show resolved Hide resolved
path: artifacts
if-no-files-found: ignore
include-hidden-files: true
Expand All @@ -303,7 +319,7 @@ jobs:

- name: Set the base sha
# Only needed when publishing results.
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/trunk' && ! inputs.memcached }}
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/trunk' && ! inputs.memcached && ! inputs.multisite }}
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
id: base-sha
with:
Expand All @@ -314,7 +330,7 @@ jobs:

- name: Set commit details
# Only needed when publishing results.
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/trunk' && ! inputs.memcached }}
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/trunk' && ! inputs.memcached && ! inputs.multisite }}
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
id: commit-timestamp
with:
Expand All @@ -325,7 +341,7 @@ jobs:

- name: Publish performance results
# Only publish results on pushes to trunk.
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/trunk' && ! inputs.memcached }}
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/trunk' && ! inputs.memcached && ! inputs.multisite }}
env:
BASE_SHA: ${{ steps.base-sha.outputs.result }}
COMMITTED_AT: ${{ steps.commit-timestamp.outputs.result }}
Expand Down
6 changes: 5 additions & 1 deletion tests/performance/compare-results.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ if ( process.env.GITHUB_SHA ) {
);
}

summaryMarkdown += `<details><summary>Results</summary>`;
swissspidy marked this conversation as resolved.
Show resolved Hide resolved

for ( const { title, results } of afterStats ) {
const prevStat = beforeStats.find( ( s ) => s.title === title );

Expand Down Expand Up @@ -143,10 +145,12 @@ for ( const { title, results } of afterStats ) {
console.log( '(no results)' );
}

summaryMarkdown += `**${ title }**\n\n`;
summaryMarkdown += `<b>${ title }</b>\n\n`;
summaryMarkdown += `${ formatAsMarkdownTable( rows ) }\n`;
}

summaryMarkdown += `</details>`;

writeFileSync(
join( process.env.WP_ARTIFACTS_PATH, '/performance-results.md' ),
summaryMarkdown
Expand Down
14 changes: 10 additions & 4 deletions tests/performance/log-results.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,18 @@ const { median, parseFile, accumulateValues } = require( './utils' );
const testSuiteMap = {
'Admin › Locale: en_US': 'admin',
'Admin › Locale: de_DE': 'admin-l10n',
'Front End › Theme: twentytwentyone, Locale: en_US': 'home-classic-theme',
'Front End › Theme: twentytwentyone, Locale: de_DE':
'Homepage › Theme: twentytwentyone, Locale: en_US': 'home-classic-theme',
'Homepage › Theme: twentytwentyone, Locale: de_DE':
'home-classic-theme-l10n',
'Front End › Theme: twentytwentythree, Locale: en_US': 'home-block-theme',
'Front End › Theme: twentytwentythree, Locale: de_DE':
'Homepage › Theme: twentytwentythree, Locale: en_US': 'home-block-theme',
'Homepage › Theme: twentytwentythree, Locale: de_DE':
'home-block-theme-l10n',
'Homepage › Theme: twentytwentyfour, Locale: en_US': 'home-twentytwentyfour',
'Homepage › Theme: twentytwentyfour, Locale: de_DE':
'home-twentytwentyfour-l10n',
'Homepage › Theme: twentytwentyfive, Locale: en_US': 'home-twentytwentyfive',
'Homepage › Theme: twentytwentyfive, Locale: de_DE':
'home-twentytwentyfive-l10n',
swissspidy marked this conversation as resolved.
Show resolved Hide resolved
};

/**
Expand Down
9 changes: 6 additions & 3 deletions tests/performance/specs/admin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ import { test } from '@wordpress/e2e-test-utils-playwright';
/**
* Internal dependencies
*/
import { camelCaseDashes } from '../utils';
import { camelCaseDashes, locales } from '../utils';

const results = {
timeToFirstByte: [],
};

const locales = [ 'en_US', 'de_DE' ];

test.describe( 'Admin', () => {
for ( const locale of locales ) {
test.describe( `Locale: ${ locale }`, () => {
Expand Down Expand Up @@ -47,9 +45,14 @@ test.describe( 'Admin', () => {
const iterations = Number( process.env.TEST_RUNS );
for ( let i = 1; i <= iterations; i++ ) {
test( `Measure load time metrics (${ i } of ${ iterations })`, async ( {
page,
admin,
metrics,
} ) => {
// Clear caches using the clear-cache.php mu-plugin. Not actually loading the page.
await page.goto( '/?clear_cache' );

// This is the actual page to test.
await admin.visitAdminPage( '/' );

const serverTiming = await metrics.getServerTiming();
Expand Down
12 changes: 6 additions & 6 deletions tests/performance/specs/home.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,15 @@ import { test } from '@wordpress/e2e-test-utils-playwright';
/**
* Internal dependencies
*/
import { camelCaseDashes } from '../utils';
import { camelCaseDashes, themes, locales } from '../utils';

const results = {
timeToFirstByte: [],
largestContentfulPaint: [],
lcpMinusTtfb: [],
};

const themes = [ 'twentytwentyone', 'twentytwentythree', 'twentytwentyfour', 'twentytwentyfive' ];

const locales = [ 'en_US', 'de_DE' ];

test.describe( 'Front End', () => {
test.describe( 'Homepage', () => {
test.use( {
storageState: {}, // User will be logged out.
} );
Expand Down Expand Up @@ -54,6 +50,10 @@ test.describe( 'Front End', () => {
page,
metrics,
} ) => {
// Clear caches using the clear-cache.php mu-plugin. Not actually loading the page.
await page.goto( '/?clear_cache' );
swissspidy marked this conversation as resolved.
Show resolved Hide resolved

// This is the actual page to test.
await page.goto( '/' );

const serverTiming = await metrics.getServerTiming();
Expand Down
79 changes: 79 additions & 0 deletions tests/performance/specs/single-post.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* WordPress dependencies
*/
import { test } from '@wordpress/e2e-test-utils-playwright';

/**
* Internal dependencies
*/
import { camelCaseDashes, themes, locales } from '../utils';

const results = {
timeToFirstByte: [],
largestContentfulPaint: [],
lcpMinusTtfb: [],
};

test.describe( 'Single Post', () => {
test.use( {
storageState: {}, // User will be logged out.
} );

for ( const theme of themes ) {
for ( const locale of locales ) {
test.describe( `Theme: ${ theme }, Locale: ${ locale }`, () => {
test.beforeAll( async ( { requestUtils } ) => {
await requestUtils.activateTheme( theme );
await requestUtils.updateSiteSettings( {
language: 'en_US' === locale ? '' : locale,
} );
} );

test.afterAll( async ( { requestUtils }, testInfo ) => {
await testInfo.attach( 'results', {
body: JSON.stringify( results, null, 2 ),
contentType: 'application/json',
} );

await requestUtils.updateSiteSettings( {
language: '',
} );

results.largestContentfulPaint = [];
results.timeToFirstByte = [];
results.lcpMinusTtfb = [];
} );

const iterations = Number( process.env.TEST_RUNS );
for ( let i = 1; i <= iterations; i++ ) {
test( `Measure load time metrics (${ i } of ${ iterations })`, async ( {
page,
metrics,
} ) => {
// Clear caches using the clear-cache.php mu-plugin. Not actually loading the page.
await page.goto( '/?clear_cache' );

// This is the actual page to test.
await page.goto( '/2018/11/03/block-image/' );
swissspidy marked this conversation as resolved.
Show resolved Hide resolved

const serverTiming = await metrics.getServerTiming();

for ( const [ key, value ] of Object.entries(
serverTiming
) ) {
results[ camelCaseDashes( key ) ] ??= [];
results[ camelCaseDashes( key ) ].push( value );
}

const ttfb = await metrics.getTimeToFirstByte();
const lcp = await metrics.getLargestContentfulPaint();

results.largestContentfulPaint.push( lcp );
results.timeToFirstByte.push( ttfb );
results.lcpMinusTtfb.push( lcp - ttfb );
} );
}
} );
}
}
} );
6 changes: 6 additions & 0 deletions tests/performance/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ const { join } = require( 'node:path' );

process.env.WP_ARTIFACTS_PATH ??= join( process.cwd(), 'artifacts' );

const locales = [ 'en_US', 'de_DE' ];

const themes = [ 'twentytwentyone', 'twentytwentythree', 'twentytwentyfour', 'twentytwentyfive' ];

/**
* Parse test files into JSON objects.
*
Expand Down Expand Up @@ -189,4 +193,6 @@ module.exports = {
standardDeviation,
medianAbsoluteDeviation,
accumulateValues,
themes,
locales,
};
27 changes: 27 additions & 0 deletions tests/performance/wp-content/mu-plugins/clear-cache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

add_action(
'plugins_loaded',
static function () {
if ( isset( $_GET['clear_cache'] ) ) {
if ( function_exists( 'opcache_reset' ) ) {
opcache_reset();
}

if ( function_exists( 'apcu_clear_cache' ) ) {
apcu_clear_cache();
}

wp_cache_flush();

delete_expired_transients( true );

clearstatcache( true );

status_header( 202 );

die;
}
},
1
);
Loading