Commit 46f5cd52fe6 for woocommerce
commit 46f5cd52fe6f41e771e127f5dca5603b77abe7fb
Author: Vladimir Reznichenko <kalessil@gmail.com>
Date: Thu Apr 23 21:28:55 2026 +0200
[Performance] BFCM stress-test config fo K6 (#64349)
diff --git a/plugins/woocommerce/package.json b/plugins/woocommerce/package.json
index 72f7d2e774e..8718b7b4a80 100644
--- a/plugins/woocommerce/package.json
+++ b/plugins/woocommerce/package.json
@@ -29,7 +29,7 @@
"env:destroy": "pnpm wp-env destroy",
"env:dev": "pnpm wp-env start --update",
"env:down": "pnpm wp-env stop",
- "env:performance-init": "./tests/performance/bin/init-sample-products.sh",
+ "env:performance-init": "./tests/performance/bin/init-environment.sh",
"env:restart": "pnpm wp-env destroy && pnpm wp-env start --update",
"env:start": "pnpm wp-env start",
"env:start:blocks": "pnpm --filter='@woocommerce/block-library' env:start && pnpm playwright install chromium",
diff --git a/plugins/woocommerce/tests/performance/README.md b/plugins/woocommerce/tests/performance/README.md
index 21fc858be2f..adafcf7ff2d 100644
--- a/plugins/woocommerce/tests/performance/README.md
+++ b/plugins/woocommerce/tests/performance/README.md
@@ -50,7 +50,7 @@ Alternatively the k6 docker image can be used to execute tests.
Before using the tests a test environment is needed to run against.
-We first spin up an environment using `wp-env` and configure that environment with the necessary plugins and data using the Initialization Script [`init-sample-products.sh`](https://github.com/woocommerce/woocommerce/tree/trunk/plugins/woocommerce/tests/performance/bin/init-sample-products.sh) that will set up a shop with sample products imported and the shop settings (payment method, permalinks, address etc) needed for the tests already set. It is recommended using this to just see the tests in action.
+We first spin up an environment using `wp-env` and configure that environment with the necessary plugins and data using the Initialization Script [`init-environment.sh`](https://github.com/woocommerce/woocommerce/tree/trunk/plugins/woocommerce/tests/performance/bin/init-environment.sh) that will set up a shop with sample products imported and the shop settings (payment method, permalinks, address etc) needed for the tests already set. It is recommended using this to just see the tests in action.
```sh
pnpm env:dev --filter=@woocommerce/plugin-woocommerce
diff --git a/plugins/woocommerce/tests/performance/bin/init-sample-products.sh b/plugins/woocommerce/tests/performance/bin/init-environment.sh
similarity index 58%
rename from plugins/woocommerce/tests/performance/bin/init-sample-products.sh
rename to plugins/woocommerce/tests/performance/bin/init-environment.sh
index f9bf74fdee2..395f9b9b416 100755
--- a/plugins/woocommerce/tests/performance/bin/init-sample-products.sh
+++ b/plugins/woocommerce/tests/performance/bin/init-environment.sh
@@ -35,4 +35,29 @@ wp-env run tests-cli wp theme install storefront --activate
wp-env run tests-cli wp config set DISABLE_WP_CRON true --raw --type=constant
wp-env run tests-cli wp config set WP_HTTP_BLOCK_EXTERNAL true --raw --type=constant
+# Resolve container names once; fail loudly if wp-env is not running.
+_wp_container="$(docker ps --filter name=tests-wordpress --format '{{.Names}}' | head -1)"
+_db_container="$(docker ps --filter name=tests-mysql --format '{{.Names}}' | head -1)"
+if [ -z "$_wp_container" ] || [ -z "$_db_container" ]; then
+ echo "Error: wp-env containers not found. Run 'pnpm env:perf' first." >&2
+ exit 1
+fi
+
+# Remove container-level strains for cleaner performance metrics: OPcache.
+docker exec -u root "$_wp_container" bash -c \
+ "printf '[opcache]\nopcache.enable=1\nopcache.memory_consumption=256\nopcache.max_accelerated_files=20000\nopcache.validate_timestamps=1\nopcache.revalidate_freq=0\n' > /usr/local/etc/php/conf.d/perf-opcache.ini"
+docker restart "$_wp_container"
+
+# Remove container-level strains for cleaner performance metrics: DB buffer and connections pool.
+docker exec -u root "$_db_container" bash -c "printf '[mysqld]\ninnodb_buffer_pool_size=1073741824\ninnodb_flush_log_at_trx_commit=2\n' > /etc/mysql/conf.d/perf-tuning.cnf"
+docker restart "$_db_container"
+_deadline=$((SECONDS + 30))
+until docker exec "$_db_container" mariadb -u root -ppassword -e "SELECT 1" &>/dev/null; do
+ if [ $SECONDS -ge $_deadline ]; then
+ echo "Error: MariaDB did not become ready within 30 seconds." >&2
+ exit 1
+ fi
+ sleep 0.5
+done
+
echo "Success! Your E2E Test Environment is now ready."
diff --git a/plugins/woocommerce/tests/performance/tests/bfcm.js b/plugins/woocommerce/tests/performance/tests/bfcm.js
new file mode 100644
index 00000000000..9c5bf8ddae2
--- /dev/null
+++ b/plugins/woocommerce/tests/performance/tests/bfcm.js
@@ -0,0 +1,96 @@
+/**
+ * Internal dependencies
+ */
+import { cart } from '../requests/shopper/cart.js';
+import { checkoutGuest } from '../requests/shopper/checkout-guest.js';
+import { checkoutCustomerLogin } from '../requests/shopper/checkout-customer-login.js';
+
+// Regression and stabilization indicators (for AI agents comparing runs):
+// This test runs at the environment's saturation ceiling — thresholds will fail by design.
+// Use the following metrics to detect regressions (numbers go up) or improvements (numbers go down):
+// - http_req_failed rate — baseline ~4%; target <1%; regressions push this higher.
+// - dropped_iterations — baseline ~278; fewer = system handled more load cleanly.
+// - http_req_duration p(50) — baseline ~101ms; the fast-path latency; regressions surface here first.
+// - iteration_duration avg — baseline ~52s; lower = checkout flow completing faster under load.
+// - Store API checkout avg — baseline ~16s; the heaviest per-request operation; most sensitive to checkout optimizations.
+// A PR that reduces DB queries or checkout overhead will move all of the above in the right direction even
+// if the test still "fails" thresholds — less failing is a measurable win. Baseline is as of April 2026.
+
+export const options = {
+ // Saturation profile (M4 Pro, wp-env defaults):
+ // - Bottleneck: Apache prefork MaxRequestWorkers=150 (not DB — MariaDB Threads_running stays at 1).
+ // - At 0.8 checkout/s workers plateau at ~37/150, spike to ~56/150, then self-correct — bounded, no cascade.
+ // - At 1.0/s workers climb unboundedly to ~117/150, causing request queuing and timeouts.
+ // - Requires a clean Apache baseline: restart the WordPress container between runs (init-environment.sh).
+ // - To raise the ceiling: increase MaxRequestWorkers in Apache MPM prefork config and re-profile.
+ scenarios: {
+ // Guest checkout: 60% of checkouts.
+ checkout_guest_bfcm: {
+ executor: 'ramping-arrival-rate',
+ exec: 'checkoutGuestFlow',
+ startRate: 1,
+ timeUnit: '10s',
+ preAllocatedVUs: 6,
+ maxVUs: 15,
+ stages: [
+ { duration: '4m', target: 5 }, // Ramp to peak.
+ { duration: '8m', target: 5 }, // Sustain peak.
+ { duration: '2m', target: 0 }, // Ramp down.
+ ],
+ },
+ // Authenticated checkout: 40% of checkouts.
+ checkout_customer_bfcm: {
+ executor: 'ramping-arrival-rate',
+ exec: 'checkoutCustomerLoginFlow',
+ startRate: 1,
+ timeUnit: '10s',
+ preAllocatedVUs: 4,
+ maxVUs: 10,
+ stages: [
+ { duration: '4m', target: 3 }, // Ramp to peak.
+ { duration: '8m', target: 3 }, // Sustain peak.
+ { duration: '2m', target: 0 }, // Ramp down.
+ ],
+ },
+ },
+ thresholds: {
+ // Aggregate thresholds across all requests.
+ http_req_duration: [
+ 'p(50)<200',
+ 'p(90)<1000',
+ 'p(95)<1500',
+ 'p(99.9)<3000',
+ ],
+ http_req_failed: [ 'rate<0.01' ],
+
+ // Per-request thresholds: cart workflow.
+ 'http_req_duration{name:Shopper - wc-ajax=add_to_cart}': [
+ 'p(95)<500',
+ ],
+ 'http_req_duration{name:Shopper - wc-ajax=get_refreshed_fragments}': [
+ 'p(95)<200',
+ ],
+ 'http_req_duration{name:Shopper - View Cart}': [ 'p(95)<500' ],
+
+ // Per-request thresholds: checkout workflow.
+ 'http_req_duration{name:Shopper - View Checkout}': [ 'p(95)<1000' ],
+ 'http_req_duration{name:Shopper - Login to Checkout}': [ 'p(95)<750' ],
+ 'http_req_duration{name:Shopper - Store API update-customer}': [
+ 'p(95)<500',
+ ],
+ 'http_req_duration{name:Shopper - Store API checkout}': [
+ 'p(95)<3000',
+ ],
+ 'http_req_duration{name:Shopper - Order Received}': [ 'p(95)<1000' ],
+ },
+};
+
+export function checkoutGuestFlow() {
+ cart();
+ checkoutGuest();
+}
+
+export function checkoutCustomerLoginFlow() {
+ cart();
+ checkoutCustomerLogin();
+}