From 9079c16d164ef4fd2497f19bc53319ac3e33b460 Mon Sep 17 00:00:00 2001 From: Nerivec <62446222+Nerivec@users.noreply.github.com> Date: Wed, 27 Aug 2025 20:12:30 +0200 Subject: [PATCH] chore: switch benchmarking tool (#28396) Co-authored-by: Koen Kanters --- .github/workflows/ci.yml | 13 +- package.json | 1 - pnpm-lock.yaml | 261 --------------------------------------- test/benchOptions.ts | 14 +++ test/controller.bench.ts | 151 +++++++++++----------- test/vitest.config.mts | 3 +- 6 files changed, 93 insertions(+), 350 deletions(-) create mode 100644 test/benchOptions.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 94f14e474..e0e85d7fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,9 @@ jobs: ci: runs-on: ubuntu-latest permissions: - id-token: write + id-token: write # for npm publish + actions: read # for Nerivec/action-ci-bench + pull-requests: write # for Nerivec/action-ci-bench steps: - uses: actions/checkout@v5 if: (github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/')) && github.event_name == 'push' @@ -50,10 +52,13 @@ jobs: - name: Bench if: github.ref == 'refs/heads/dev' || (github.event_name == 'pull_request' && !startsWith(github.head_ref, 'release-please-')) - uses: CodSpeedHQ/action@v3 + uses: Nerivec/action-ci-bench@main with: - run: pnpm run bench - token: ${{ secrets.CODSPEED_TOKEN }} + token: ${{ secrets.GITHUB_TOKEN }} + compare-against: dev + base-cmd: npx vitest bench --run --config ./test/vitest.config.mts --outputJson bench.json + compare-cmd: npx vitest bench --run --config ./test/vitest.config.mts --compare bench.json + base-result: bench.json - name: Log in to the Docker container registry if: (github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/')) && github.event_name == 'push' diff --git a/package.json b/package.json index f0f49afda..cb7dea875 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,6 @@ }, "devDependencies": { "@biomejs/biome": "^2.2.2", - "@codspeed/vitest-plugin": "^4.0.1", "@types/finalhandler": "^1.2.3", "@types/humanize-duration": "^3.27.4", "@types/js-yaml": "^4.0.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4f2f58384..dd7c96680 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -90,9 +90,6 @@ importers: '@biomejs/biome': specifier: ^2.2.2 version: 2.2.2 - '@codspeed/vitest-plugin': - specifier: ^4.0.1 - version: 4.0.1(vite@6.3.5(@types/node@24.3.0))(vitest@3.2.4(@types/node@24.3.0)) '@types/finalhandler': specifier: ^1.2.3 version: 1.2.4 @@ -218,15 +215,6 @@ packages: cpu: [x64] os: [win32] - '@codspeed/core@4.0.1': - resolution: {integrity: sha512-fJ53arfgtzCDZa8DuGJhpTZ3Ll9A1uW5nQ2jSJnfO4Hl5MRD2cP8P4vPvIUAGbdbjwCxR1jat6cW8OloMJkJXw==} - - '@codspeed/vitest-plugin@4.0.1': - resolution: {integrity: sha512-aqmrPJzX9cD50UWDsOyih5L5WcEYlNQg3u84sJJ9ZuuLApA51w+LGxk6Xbyb8LJF9n/CwM94HKHV/qArfnvDoQ==} - peerDependencies: - vite: ^4.2.0 || ^5.0.0 || ^6.0.0 - vitest: '>=1.2.2' - '@colors/colors@1.6.0': resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} engines: {node: '>=0.1.90'} @@ -656,12 +644,6 @@ packages: async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} - asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - - axios@1.10.0: - resolution: {integrity: sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==} - balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -703,10 +685,6 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} - engines: {node: '>= 0.4'} - chai@5.2.0: resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} engines: {node: '>=12'} @@ -737,10 +715,6 @@ packages: colorspace@1.1.4: resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} - combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - commist@3.2.0: resolution: {integrity: sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==} @@ -781,10 +755,6 @@ packages: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} - delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} @@ -793,10 +763,6 @@ packages: resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} engines: {node: '>=6'} - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} - eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -816,25 +782,9 @@ packages: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} - - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - engines: {node: '>= 0.4'} - - es-set-tostringtag@2.1.0: - resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} - engines: {node: '>= 0.4'} - esbuild@0.25.5: resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==} engines: {node: '>=18'} @@ -893,30 +843,13 @@ packages: resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==} engines: {node: '>= 0.8'} - find-up@6.3.0: - resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - fn.name@1.1.0: resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} - follow-redirects@1.15.9: - resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} - form-data@4.0.3: - resolution: {integrity: sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==} - engines: {node: '>= 6'} - fresh@2.0.0: resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} engines: {node: '>= 0.8'} @@ -926,17 +859,6 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - get-intrinsic@1.3.0: - resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} - engines: {node: '>= 0.4'} - - get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} - glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true @@ -950,26 +872,10 @@ packages: resolution: {integrity: sha512-mTCC51QFadK75MvAhrL5nPVIP291NjML1guo10Sa7Yj04tJU4V++Vgm780NIddg9etQD9D8FM67hFGqM8EE2HQ==} engines: {node: '>= 0.2.5'} - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} - has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} - - has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - help-me@5.0.0: resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} @@ -1068,10 +974,6 @@ packages: lie@3.3.0: resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} - locate-path@7.2.0: - resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - logform@2.7.0: resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==} engines: {node: '>= 12.0.0'} @@ -1096,22 +998,10 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - mime-db@1.54.0: resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} engines: {node: '>= 0.6'} - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - mime-types@3.0.1: resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} engines: {node: '>= 0.6'} @@ -1183,14 +1073,6 @@ packages: one-time@1.0.0: resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} - p-limit@4.0.0: - resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - p-locate@6.0.0: - resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -1201,10 +1083,6 @@ packages: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} - path-exists@5.0.0: - resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -1242,9 +1120,6 @@ packages: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} - proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} @@ -1600,10 +1475,6 @@ packages: utf-8-validate: optional: true - yocto-queue@1.2.1: - resolution: {integrity: sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==} - engines: {node: '>=12.20'} - zigbee-herdsman-converters@25.9.0: resolution: {integrity: sha512-KF4EDzdM804EI7wNSyC5nHF8owYTq6jYbgpbYygb/05PlHVTsZ9kPUuhqcgWC4Cf4v/OFal8RT49paqBy174bA==} @@ -1681,23 +1552,6 @@ snapshots: '@biomejs/cli-win32-x64@2.2.2': optional: true - '@codspeed/core@4.0.1': - dependencies: - axios: 1.10.0 - find-up: 6.3.0 - form-data: 4.0.3 - node-gyp-build: 4.8.4 - transitivePeerDependencies: - - debug - - '@codspeed/vitest-plugin@4.0.1(vite@6.3.5(@types/node@24.3.0))(vitest@3.2.4(@types/node@24.3.0))': - dependencies: - '@codspeed/core': 4.0.1 - vite: 6.3.5(@types/node@24.3.0) - vitest: 3.2.4(@types/node@24.3.0) - transitivePeerDependencies: - - debug - '@colors/colors@1.6.0': {} '@dabh/diagnostics@2.0.3': @@ -2040,16 +1894,6 @@ snapshots: async@3.2.6: {} - asynckit@0.4.0: {} - - axios@1.10.0: - dependencies: - follow-redirects: 1.15.9 - form-data: 4.0.3 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - balanced-match@1.0.2: {} base64-js@1.5.1: {} @@ -2099,11 +1943,6 @@ snapshots: cac@6.7.14: {} - call-bind-apply-helpers@1.0.2: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - chai@5.2.0: dependencies: assertion-error: 2.0.1 @@ -2141,10 +1980,6 @@ snapshots: color: 3.2.1 text-hex: 1.0.0 - combined-stream@1.0.8: - dependencies: - delayed-stream: 1.0.0 - commist@3.2.0: {} concat-stream@2.0.0: @@ -2174,20 +2009,12 @@ snapshots: deep-eql@5.0.2: {} - delayed-stream@1.0.0: {} - depd@2.0.0: {} dns-packet@5.6.1: dependencies: '@leichtgewicht/ip-codec': 2.0.5 - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-errors: 1.3.0 - gopd: 1.2.0 - eastasianwidth@0.2.0: {} ee-first@1.1.1: {} @@ -2200,23 +2027,8 @@ snapshots: encodeurl@2.0.0: {} - es-define-property@1.0.1: {} - - es-errors@1.3.0: {} - es-module-lexer@1.7.0: {} - es-object-atoms@1.1.1: - dependencies: - es-errors: 1.3.0 - - es-set-tostringtag@2.1.0: - dependencies: - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - esbuild@0.25.5: optionalDependencies: '@esbuild/aix-ppc64': 0.25.5 @@ -2296,53 +2108,18 @@ snapshots: transitivePeerDependencies: - supports-color - find-up@6.3.0: - dependencies: - locate-path: 7.2.0 - path-exists: 5.0.0 - fn.name@1.1.0: {} - follow-redirects@1.15.9: {} - foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 signal-exit: 4.1.0 - form-data@4.0.3: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - es-set-tostringtag: 2.1.0 - hasown: 2.0.2 - mime-types: 2.1.35 - fresh@2.0.0: {} fsevents@2.3.3: optional: true - function-bind@1.1.2: {} - - get-intrinsic@1.3.0: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 - glob@10.4.5: dependencies: foreground-child: 3.3.1 @@ -2363,20 +2140,8 @@ snapshots: glossy@0.1.7: {} - gopd@1.2.0: {} - has-flag@4.0.0: {} - has-symbols@1.1.0: {} - - has-tostringtag@1.0.2: - dependencies: - has-symbols: 1.1.0 - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - help-me@5.0.0: {} html-escaper@2.0.2: {} @@ -2474,10 +2239,6 @@ snapshots: dependencies: immediate: 3.0.6 - locate-path@7.2.0: - dependencies: - p-locate: 6.0.0 - logform@2.7.0: dependencies: '@colors/colors': 1.6.0 @@ -2507,16 +2268,8 @@ snapshots: dependencies: semver: 7.7.2 - math-intrinsics@1.1.0: {} - - mime-db@1.52.0: {} - mime-db@1.54.0: {} - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - mime-types@3.0.1: dependencies: mime-db: 1.54.0 @@ -2601,22 +2354,12 @@ snapshots: dependencies: fn.name: 1.1.0 - p-limit@4.0.0: - dependencies: - yocto-queue: 1.2.1 - - p-locate@6.0.0: - dependencies: - p-limit: 4.0.0 - package-json-from-dist@1.0.1: {} pako@1.0.11: {} parseurl@1.3.3: {} - path-exists@5.0.0: {} - path-key@3.1.1: {} path-scurry@1.11.1: @@ -2647,8 +2390,6 @@ snapshots: process@0.11.10: {} - proxy-from-env@1.1.0: {} - range-parser@1.2.1: {} readable-stream@2.3.8: @@ -3037,8 +2778,6 @@ snapshots: ws@8.18.3: {} - yocto-queue@1.2.1: {} - zigbee-herdsman-converters@25.9.0: dependencies: buffer-crc32: 1.0.0 diff --git a/test/benchOptions.ts b/test/benchOptions.ts new file mode 100644 index 000000000..df2ac463d --- /dev/null +++ b/test/benchOptions.ts @@ -0,0 +1,14 @@ +import {hrtime} from "node:process"; +import type {bench} from "vitest"; + +export const BENCH_OPTIONS: NonNullable[2]> = { + throws: true, + warmupTime: 1000, + now: () => Number(hrtime.bigint()) / 1e6, + setup: (_task, mode) => { + // Run the garbage collector before warmup at each cycle + if (mode === "warmup" && typeof globalThis.gc === "function") { + globalThis.gc(); + } + }, +}; diff --git a/test/controller.bench.ts b/test/controller.bench.ts index acfdf7ef2..31d72fee1 100644 --- a/test/controller.bench.ts +++ b/test/controller.bench.ts @@ -1,6 +1,6 @@ import {existsSync, mkdirSync} from "node:fs"; import stringify from "json-stable-stringify-without-jsonify"; -import {afterAll, afterEach, beforeAll, beforeEach, bench, describe} from "vitest"; +import {bench, describe} from "vitest"; import {Zcl, Zdo, ZSpec} from "zigbee-herdsman"; import type Adapter from "zigbee-herdsman/dist/adapter/adapter"; import type {ZclPayload} from "zigbee-herdsman/dist/adapter/events"; @@ -12,6 +12,7 @@ import type {DeviceType} from "zigbee-herdsman/dist/controller/tstype"; import {Foundation} from "zigbee-herdsman/dist/zspec/zcl/definition/foundation"; import type {RequestToResponseMap} from "zigbee-herdsman/dist/zspec/zdo/definition/tstypes"; import data from "../lib/util/data"; +import {BENCH_OPTIONS} from "./benchOptions"; process.env.ZIGBEE2MQTT_DATA = "data-bench"; data._testReload(); @@ -433,69 +434,9 @@ const initController = async () => { }; describe("Controller with dummy zigbee/mqtt", () => { - describe("defaults start & stop", () => { - beforeEach(async () => { - initDevices(); - initGroups(); - await initSettings(); - await initController(); - }); - - afterEach(() => { - unmockGlobalThis(); - }); - - bench( - "[defaults] start & stop controller", - async () => { - const mockedGlobal = mockGlobalThis(); - - await controller.start(); - await settle(mockedGlobal); - - if ((await controller.zigbee.getCoordinatorVersion()).type !== "Dummy") { - throw new Error("Invalid"); - } - - await controller.stop(); - }, - {throws: true}, - ); - }); - - describe("HA start & stop", () => { - beforeEach(async () => { - initDevices(); - initGroups(); - await initSettings([[["homeassistant", "enabled"], true]]); - await initController(); - }); - - afterEach(() => { - unmockGlobalThis(); - }); - - bench( - "[HA] start & stop controller", - async () => { - const mockedGlobal = mockGlobalThis(); - - await controller.start(); - controller.mqtt.onMessage("homeassistant/status", Buffer.from("online", "utf8")); - await settle(mockedGlobal); - - if ((await controller.zigbee.getCoordinatorVersion()).type !== "Dummy") { - throw new Error("Invalid"); - } - - await controller.stop(); - }, - {throws: true}, - ); - }); - - describe("defaults runtime", () => { - beforeAll(async () => { + bench( + "[defaults] start & stop controller", + async () => { initDevices(); initGroups(); await initSettings(); @@ -504,12 +445,56 @@ describe("Controller with dummy zigbee/mqtt", () => { await controller.start(); await settle(mockedGlobal); - }); - afterAll(async () => { + if ((await controller.zigbee.getCoordinatorVersion()).type !== "Dummy") { + throw new Error("Invalid"); + } + await controller.stop(); unmockGlobalThis(); - }); + }, + BENCH_OPTIONS, + ); + + bench( + "[HA] start & stop controller", + async () => { + initDevices(); + initGroups(); + await initSettings([[["homeassistant", "enabled"], true]]); + await initController(); + const mockedGlobal = mockGlobalThis(); + + await controller.start(); + controller.mqtt.onMessage("homeassistant/status", Buffer.from("online", "utf8")); + await settle(mockedGlobal); + + if ((await controller.zigbee.getCoordinatorVersion()).type !== "Dummy") { + throw new Error("Invalid"); + } + + await controller.stop(); + unmockGlobalThis(); + }, + BENCH_OPTIONS, + ); + + describe("defaults runtime", () => { + const setup: NonNullable[2]>["setup"] = async (task, mode) => { + BENCH_OPTIONS.setup!(task, mode); + initDevices(); + initGroups(); + await initSettings(); + await initController(); + const mockedGlobal = mockGlobalThis(); + + await controller.start(); + await settle(mockedGlobal); + }; + const teardown = async () => { + await controller.stop(); + unmockGlobalThis(); + }; bench( "[defaults] receive device message", @@ -528,7 +513,7 @@ describe("Controller with dummy zigbee/mqtt", () => { }); await settle(mockedGlobal); }, - {throws: true}, + {...BENCH_OPTIONS, setup, teardown}, ); bench( @@ -539,7 +524,7 @@ describe("Controller with dummy zigbee/mqtt", () => { controller.mqtt.onMessage("zigbee2mqtt/0xf1f1f1f1f1f1f1f1/set", Buffer.from(`{"state": "OFF"}`, "utf8")); await settle(mockedGlobal); }, - {throws: true}, + {...BENCH_OPTIONS, setup, teardown}, ); bench( @@ -562,12 +547,13 @@ describe("Controller with dummy zigbee/mqtt", () => { throw new Error("Invalid state"); } }, - {throws: true}, + {...BENCH_OPTIONS, setup, teardown}, ); }); describe("defaults/stress runtime", () => { - beforeAll(async () => { + const setup: NonNullable[2]>["setup"] = async (task, mode) => { + BENCH_OPTIONS.setup!(task, mode); initDevices(); initGroups(); addManyDevices(); @@ -577,12 +563,12 @@ describe("Controller with dummy zigbee/mqtt", () => { await controller.start(); await settle(mockedGlobal); - }, 60000); + }; - afterAll(async () => { + const teardown = async () => { await controller.stop(); unmockGlobalThis(); - }); + }; // this is mostly just to confirm the number of devices does not influence the processing (much) bench( @@ -602,12 +588,13 @@ describe("Controller with dummy zigbee/mqtt", () => { }); await settle(mockedGlobal); }, - {throws: true}, + {...BENCH_OPTIONS, setup, teardown}, ); }); describe("HA runtime", () => { - beforeAll(async () => { + const setup: NonNullable[2]>["setup"] = async (task, mode) => { + BENCH_OPTIONS.setup!(task, mode); initDevices(); initGroups(); await initSettings([[["homeassistant", "enabled"], true]]); @@ -617,12 +604,12 @@ describe("Controller with dummy zigbee/mqtt", () => { await controller.start(); controller.mqtt.onMessage("homeassistant/status", Buffer.from("online", "utf8")); await settle(mockedGlobal); - }); + }; - afterAll(async () => { + const teardown = async () => { await controller.stop(); unmockGlobalThis(); - }); + }; bench( "[HA] receive device message", @@ -641,7 +628,7 @@ describe("Controller with dummy zigbee/mqtt", () => { }); await settle(mockedGlobal); }, - {throws: true}, + {...BENCH_OPTIONS, setup, teardown}, ); bench( @@ -652,7 +639,7 @@ describe("Controller with dummy zigbee/mqtt", () => { controller.mqtt.onMessage("zigbee2mqtt/0xf1f1f1f1f1f1f1f1/set", Buffer.from(`{"state": "OFF"}`, "utf8")); await settle(mockedGlobal); }, - {throws: true}, + {...BENCH_OPTIONS, setup, teardown}, ); bench( @@ -666,7 +653,7 @@ describe("Controller with dummy zigbee/mqtt", () => { ); await settle(mockedGlobal); }, - {throws: true}, + {...BENCH_OPTIONS, setup, teardown}, ); }); }); diff --git a/test/vitest.config.mts b/test/vitest.config.mts index 45e8fae44..91150cf69 100644 --- a/test/vitest.config.mts +++ b/test/vitest.config.mts @@ -1,8 +1,7 @@ -import codspeedPlugin from "@codspeed/vitest-plugin"; import {defineConfig} from "vitest/config"; export default defineConfig({ - plugins: [codspeedPlugin()], + plugins: [], test: { globals: true, onConsoleLog(_log: string, _type: "stdout" | "stderr"): boolean | undefined {