-
Notifications
You must be signed in to change notification settings - Fork 2.9k
perf: add stress test app #24279
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
Merged
spmonahan
merged 22 commits into
microsoft:master
from
spmonahan:perf/simple-stress-test
Aug 20, 2022
Merged
perf: add stress test app #24279
Changes from all commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
bb63d7b
perf: add stress test app
spmonahan f02d178
add options to perf "buildConfig" script
spmonahan e9d0806
stress-test: update webpack config
spmonahan 339de82
stress-test: add oneOf to webpack config
spmonahan de484ed
add ts config path webpack plugin
spmonahan 7c1ad24
stress-test: update webpack to automatically load pages
spmonahan d14cb39
stress-test: move test pages
spmonahan 0684283
stress-test: update griffel webpack config
spmonahan ed7f37b
start on breadth/depth for react
spmonahan c14cc2e
stress-test: move dev dependencies to root
spmonahan e7a195f
stress-test: remove new components
spmonahan 89bac31
stress-test: tsconfig changes
spmonahan da1910f
more tsconfig changes
spmonahan f11f135
stress-test: refactor for build CI
spmonahan c90b1a1
stress-test: bump fluentui/react version
spmonahan 5dc92e8
bump lage version
spmonahan 4c41e7a
stress-test: add jsdocs to scripts
spmonahan 4a2139f
stress-test: update tsconfig.json
spmonahan a89c025
stress-test: bump @fluentui/react version
spmonahan 5313d03
pr feedback
spmonahan e7332d1
stress-test: change build command name
spmonahan 94b46d0
bump @fluentui/react version
spmonahan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| { | ||
| "presets": ["@babel/env", "@babel/react", "@babel/typescript"], | ||
| "plugins": [["@babel/plugin-proposal-decorators", { "legacy": true }]] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "extends": ["plugin:@fluentui/eslint-plugin/node"], | ||
| "root": true, | ||
| "rules": { | ||
| "import/no-extraneous-dependencies": ["error", { "packageDir": ["../../", "./"] }] | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| node_modules/ | ||
| dist/ | ||
|
|
||
| benchmarks/**/*.json | ||
| benchmarks/**/results.js | ||
|
|
||
| yarn-error.log |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| .storybook/ | ||
| .vscode/ | ||
| bundle-size/ | ||
| config/ | ||
| coverage/ | ||
| e2e/ | ||
| etc/ | ||
| node_modules/ | ||
| src/ | ||
| dist/types/ | ||
| temp/ | ||
| __fixtures__ | ||
| __mocks__ | ||
| __tests__ | ||
|
|
||
| *.api.json | ||
| *.log | ||
| *.spec.* | ||
| *.stories.* | ||
| *.test.* | ||
| *.yml | ||
|
|
||
| # config files | ||
| *config.* | ||
| *rc.* | ||
| .editorconfig | ||
| .eslint* | ||
| .git* | ||
| .prettierignore |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| # @fluentui/stress-test | ||
|
|
||
| Stress Test is an application for testing Fluent UI components in "stressful" scenarios so we can evaluate performance. | ||
|
|
||
| This application is configured to support Fluent UI v8, v9 and Web Components. | ||
|
|
||
| Stress Test is a simple Webpack application as Webpack allows us to support Fluent v8, v9 and Web Components in a single app while using each version of Fluent natively (that is, the React versions of Fluent are typical React apps, the Web Component version is a typical web component app). Additionally, Griffel, a dependency of Fluent v9 provides some Webpack loaders so Stress Test needs to be able to use those. | ||
|
|
||
| ## Development | ||
|
|
||
| Use `yarn start` and select `@fluentui/stress-test` from the list of options to start the application in development mode. | ||
|
|
||
| ### Project layout | ||
|
|
||
| The project is laid out with folders for each supported version of Fluent (`v8`, `v9`, `wc`) with subfolders in each folder representing a test case. In general there should be corresponding cases between all three versions of Fluent. | ||
|
|
||
| The `shared` folder is for utilities that are shared across Fluent versions. | ||
|
|
||
| The `components` folder is also split by supported Fluent versions and is where compoenents that can be shared across test cases live. | ||
|
|
||
| The `benchmarks` folder houses Tachometer configurations and test results; and helper scripts for generating configurations and processing results. | ||
|
|
||
| ### Adding test cases | ||
|
|
||
| Currently, new test cases must be manually added. Add tests cases to the `pages` array in `webpack.config.js` and they will be generated by Webpack. This configuration keeps the different Fluent versions in separate Webpack chunks. The dev server needs to be restarted after changes to the config file. | ||
|
|
||
| ## Production | ||
|
|
||
| Run `yarn workspace @fluentui/stress-test build` from the repo root to build a static production bundle of the application. | ||
|
|
||
| Run `yarn workspace @fluentui/stress-test serve` to serve the static production bundle. | ||
|
|
||
| ## Running test cases | ||
|
|
||
| Run `yarn workspace @fluentui/stress-test bench:*` where "\*" is one of the test cases in `package.json`. | ||
|
|
||
| NOTE: Stress Test must be running, preferrably as a production build. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| const os = require('os'); | ||
|
|
||
| module.exports.getBrowsers = () => { | ||
| // https://github.com/Polymer/tachometer#webdriver-plugins | ||
| const browsers = ['chrome', 'firefox' /*'edge'*/]; | ||
|
|
||
| // if (os.type() === 'Darwin') { | ||
| // browsers.push('safari'); | ||
| // } | ||
|
|
||
| return browsers; | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| const fs = require('fs-extra'); | ||
| const { getBrowsers } = require('../browsers'); | ||
| const path = require('path'); | ||
| const yargs = require('yargs'); | ||
|
|
||
| const options = yargs | ||
| .options({ | ||
| size: { | ||
| alias: 's', | ||
| describe: 'Number of components to use in the test', | ||
| default: 100, | ||
| }, | ||
| 'add-nodes': { | ||
| alias: 'a', | ||
| describe: 'Number of components to add in the test', | ||
| }, | ||
| 'remove-nodes': { | ||
| alias: 'r', | ||
| describe: 'Number of components to remove in the test', | ||
| }, | ||
| }) | ||
| .parse(); | ||
|
|
||
| if (!options.addNodes) { | ||
| options.addNodes = options.size; | ||
| } | ||
|
|
||
| if (!options.removeNodes) { | ||
| options.removeNodes = options.size - 1; | ||
| } | ||
|
|
||
| const makeConfigJson = (browser, testCase, sampleSize = 25) => { | ||
| const json = ` | ||
| { | ||
| "$schema": "https://raw.githubusercontent.com/Polymer/tachometer/master/config.schema.json", | ||
| "sampleSize": ${sampleSize}, | ||
| "timeout": 0, | ||
| "benchmarks": [ | ||
| { | ||
| "browser": { | ||
| "name": "${browser}" | ||
| }, | ||
| "measurement": [ | ||
| { | ||
| "mode": "performance", | ||
| "entryName": "stress" | ||
| } | ||
| ], | ||
| "expand": [ | ||
| { | ||
| "name": "v8 - ${testCase}", | ||
| "url": "http://localhost:8080/v8/simple-stress/?test=${testCase}&numStartNodes=${options.size}&numAddNodes=${options.addNodes}&numRemoveNodes=${options.removeNodes}" | ||
| }, | ||
| { | ||
| "name": "v9 - ${testCase}", | ||
| "url": "http://localhost:8080/v9/simple-stress/?test=${testCase}&numStartNodes=${options.size}&numAddNodes=${options.addNodes}&numRemoveNodes=${options.removeNodes}" | ||
| }, | ||
| { | ||
| "name": "wc - ${testCase}", | ||
| "url": "http://localhost:8080/wc/simple-stress/?test=${testCase}&numStartNodes=${options.size}&numAddNodes=${options.addNodes}&numRemoveNodes=${options.removeNodes}" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| `; | ||
|
|
||
| return json; | ||
| }; | ||
|
|
||
| const browsers = getBrowsers(); | ||
| const testCases = ['mount', 'inject-styles', 'prop-update', 'add-node', 'remove-node']; | ||
|
|
||
| fs.mkdirpSync(path.join(__dirname, 'config')); | ||
| fs.mkdirpSync(path.join(__dirname, 'results')); | ||
|
|
||
| for (const browser of browsers) { | ||
| for (const testCase of testCases) { | ||
| const json = makeConfigJson(browser, testCase); | ||
| fs.writeFileSync(path.join(__dirname, 'config', [browser, testCase, 'json'].join('.')), json, { encoding: 'utf8' }); | ||
| } | ||
| } |
34 changes: 34 additions & 0 deletions
34
apps/stress-test/benchmarks/simple-stress/processResults.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| const fs = require('fs-extra'); | ||
| const { getBrowsers } = require('../browsers'); | ||
| const path = require('path'); | ||
|
|
||
| const browsers = getBrowsers(); | ||
| const testCases = ['mount', 'inject-styles', 'prop-update', 'add-node', 'remove-node']; | ||
|
|
||
| const browserData = {}; | ||
| for (const browser of browsers) { | ||
| browserData[browser] = {}; | ||
| for (const testCase of testCases) { | ||
| const contents = fs.readFileSync(path.join(__dirname, 'results', `${browser}.${testCase}.results.json`), { | ||
| encoding: 'utf8', | ||
| }); | ||
| const json = JSON.parse(contents); | ||
|
|
||
| browserData[browser][testCase] = json.benchmarks.map(test => { | ||
| return { | ||
| name: test.name, | ||
| mean: test.mean, | ||
| differences: test.differences, | ||
| samples: test.samples, | ||
| }; | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| console.log(browserData); | ||
|
|
||
| const js = ` | ||
| export const data = ${JSON.stringify(browserData, null, 4)}; | ||
| `; | ||
|
|
||
| fs.writeFileSync(path.join(__dirname, 'results', 'results.js'), js, { encoding: 'utf8' }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| /** Jest test setup file. */ | ||
|
|
||
| // Clean up created files/folders on exit, even after exceptions | ||
| // (will not catch SIGINT on windows) | ||
| const tmp = require('tmp'); | ||
| tmp.setGracefulCleanup(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| const { GriffelCSSExtractionPlugin } = require('@griffel/webpack-extraction-plugin'); | ||
| const MiniCssExtractPlugin = require('mini-css-extract-plugin'); | ||
|
|
||
| /** | ||
| * Webpack configuration object. | ||
| * @typedef {import('webpack').Configuration} WebpackConfig | ||
| */ | ||
|
|
||
| /** | ||
| * Webpack rules set. | ||
| * @typedef {import('webpack').RuleSetRule} WebpackRuleSetRule | ||
| */ | ||
|
|
||
| /** | ||
| * @type {string[]} | ||
| */ | ||
| const griffelModes = ['runtime', 'buildtime', 'extraction']; | ||
|
|
||
| /** | ||
| * @type {string} | ||
| */ | ||
| const mode = process.env.STRESS_TEST_GRIFFEL_MODE; | ||
|
|
||
| /** | ||
| * @type {string} | ||
| */ | ||
| const griffelMode = griffelModes.includes(mode) ? mode : 'runtime'; | ||
|
|
||
| /** | ||
| * @type {WebpackRuleSetRule[]} | ||
| */ | ||
| const extractionRules = [ | ||
| { | ||
| test: /\.(js|ts|tsx)$/, | ||
| // Apply "exclude" only if your dependencies **do not use** Griffel | ||
| // exclude: /node_modules/, | ||
| exclude: [/\.wc\.(ts|tsx)?$/, /v9\/simple\-stress/], | ||
| use: { | ||
| loader: GriffelCSSExtractionPlugin.loader, | ||
| }, | ||
| }, | ||
| // Add "@griffel/webpack-loader" if you use Griffel directly in your project | ||
| { | ||
| test: /\.(ts|tsx)$/, | ||
| exclude: [/node_modules/, /\.wc\.(ts|tsx)?$/], | ||
| use: { | ||
| loader: '@griffel/webpack-loader', | ||
| options: { | ||
| babelOptions: { | ||
| presets: ['@babel/preset-typescript'], | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| // "css-loader" is required to handle produced CSS assets by Griffel | ||
| // you can use "style-loader" or "MiniCssExtractPlugin.loader" to handle CSS insertion | ||
| { | ||
| test: /\.css$/, | ||
| use: [MiniCssExtractPlugin.loader, 'css-loader'], | ||
| }, | ||
| ]; | ||
|
|
||
| /** | ||
| * Take the Webpack config object and set properties to | ||
| * configure Griffel. | ||
| * | ||
| * NOTE: this function mutates the `config` object passed in to it. | ||
| * | ||
| * @param {WebpackConfig} config - Webpack configuration object to modify. | ||
| * @returns {WebpackConfig} Modified Webpack configuration object. | ||
| */ | ||
| const configureGriffel = config => { | ||
| console.log(`Griffel running in ${griffelMode} mode.`); | ||
| if (griffelMode === 'extraction') { | ||
| if (config.module.rules) { | ||
| config.module.rules = [...extractionRules, ...config.module.rules]; | ||
| } else { | ||
| config.modules.rules = extractionRules; | ||
| } | ||
|
|
||
| if (config.plugins) { | ||
| config.plugins = [...config.plugins, new MiniCssExtractPlugin(), new GriffelCSSExtractionPlugin()]; | ||
| } else { | ||
| config.plugins = [new MiniCssExtractPlugin(), new GriffelCSSExtractionPlugin()]; | ||
| } | ||
| } | ||
|
|
||
| return config; | ||
| }; | ||
|
|
||
| module.exports = { | ||
| configureGriffel, | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| // @ts-check | ||
|
|
||
| /** | ||
| * @type {import('@jest/types').Config.InitialOptions} | ||
| */ | ||
| module.exports = { | ||
| displayName: 'ssr-tests-v9', | ||
| preset: '../../jest.preset.js', | ||
| globals: { | ||
| 'ts-jest': { | ||
| tsConfig: '<rootDir>/tsconfig.spec.json', | ||
| diagnostics: false, | ||
| }, | ||
| }, | ||
| transform: { | ||
| '^.+\\.tsx?$': 'ts-jest', | ||
| }, | ||
| testEnvironment: 'node', | ||
| coverageDirectory: './coverage', | ||
| setupFilesAfterEnv: ['./config/tests.js'], | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| import { preset } from '@fluentui/scripts'; | ||
|
|
||
| preset(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| { | ||
| "name": "@fluentui/stress-test", | ||
| "version": "1.0.0", | ||
| "private": true, | ||
| "main": "index.js", | ||
| "license": "MIT", | ||
| "scripts": { | ||
| "start": "webpack-dev-server --mode=development", | ||
| "build:local": "lage build --to @fluentui/react @fluentui/web-components --verbose && yarn build:app", | ||
| "build:app": "webpack --mode=production", | ||
| "serve": "http-server ./dist", | ||
| "bench:simple-stress:build": "node ./benchmarks/simple-stress/buildConfig.js", | ||
spmonahan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "bench:simple-stress": "yarn bench:simple-stress:mount && yarn bench:simple-stress:inject-styles && yarn bench:simple-stress:prop-update && yarn bench:simple-stress:add-node && yarn bench:simple-stress:remove-node", | ||
| "bench:simple-stress:process": "node ./benchmarks/simple-stress/processResults.js", | ||
| "bench:simple-stress:mount": "yarn bench:simple-stress:mount:chrome && yarn bench:simple-stress:mount:firefox", | ||
| "bench:simple-stress:inject-styles": "yarn bench:simple-stress:inject-styles:chrome && yarn bench:simple-stress:inject-styles:firefox", | ||
| "bench:simple-stress:prop-update": "yarn bench:simple-stress:prop-update:chrome && yarn bench:simple-stress:prop-update:firefox", | ||
| "bench:simple-stress:add-node": "yarn bench:simple-stress:add-node:chrome && yarn bench:simple-stress:add-node:firefox", | ||
| "bench:simple-stress:remove-node": "yarn bench:simple-stress:remove-node:chrome && yarn bench:simple-stress:remove-node:firefox", | ||
| "bench:simple-stress:mount:chrome": "tach --config ./benchmarks/simple-stress/config/chrome.mount.json --json-file ./benchmarks/simple-stress/results/chrome.mount.results.json", | ||
| "bench:simple-stress:mount:firefox": "tach --config ./benchmarks/simple-stress/config/firefox.mount.json --json-file ./benchmarks/simple-stress/results/firefox.mount.results.json", | ||
| "bench:simple-stress:inject-styles:chrome": "tach --config ./benchmarks/simple-stress/config/chrome.inject-styles.json --json-file ./benchmarks/simple-stress/results/chrome.inject-styles.results.json", | ||
| "bench:simple-stress:inject-styles:firefox": "tach --config ./benchmarks/simple-stress/config/firefox.inject-styles.json --json-file ./benchmarks/simple-stress/results/firefox.inject-styles.results.json", | ||
| "bench:simple-stress:prop-update:chrome": "tach --config ./benchmarks/simple-stress/config/chrome.prop-update.json --json-file ./benchmarks/simple-stress/results/chrome.prop-update.results.json", | ||
| "bench:simple-stress:prop-update:firefox": "tach --config ./benchmarks/simple-stress/config/firefox.prop-update.json --json-file ./benchmarks/simple-stress/results/firefox.prop-update.results.json", | ||
| "bench:simple-stress:add-node:chrome": "tach --config ./benchmarks/simple-stress/config/chrome.add-node.json --json-file ./benchmarks/simple-stress/results/chrome.add-node.results.json", | ||
| "bench:simple-stress:add-node:firefox": "tach --config ./benchmarks/simple-stress/config/firefox.add-node.json --json-file ./benchmarks/simple-stress/results/firefox.add-node.results.json", | ||
| "bench:simple-stress:remove-node:chrome": "tach --config ./benchmarks/simple-stress/config/chrome.remove-node.json --json-file ./benchmarks/simple-stress/results/chrome.remove-node.results.json", | ||
| "bench:simple-stress:remove-node:firefox": "tach --config ./benchmarks/simple-stress/config/firefox.remove-node.json --json-file ./benchmarks/simple-stress/results/firefox.remove-node.results.json" | ||
| }, | ||
| "dependencies": { | ||
| "@fluentui/react": "^8.90.0", | ||
| "@fluentui/react-components": "^9.2.0", | ||
| "@fluentui/react-icons": "^2.0.175", | ||
| "@fluentui/web-components": "^2.5.3", | ||
| "@microsoft/fast-element": "^1.10.4", | ||
| "react": "16.14.0", | ||
| "react-dom": "16.14.0" | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.