-
-
Notifications
You must be signed in to change notification settings - Fork 14
Performance tests #597
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
base: master
Are you sure you want to change the base?
Performance tests #597
Changes from all commits
8d46376
153067a
03ac0f6
9995440
4fce15c
86cbb34
04eaa06
4fa2d3e
c90d312
2a6b34f
846c842
d7af1ff
c364b94
75bbfeb
a648792
a7f863f
622adad
abb7d3a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| const fs = require('fs'); | ||
|
|
||
| async function fetchArtifact(core, github, repo) { | ||
| const artifacts = await github.rest.actions.listArtifactsForRepo({ | ||
| owner: repo.owner, | ||
| repo: repo.repo, | ||
| }); | ||
| const filteredArtifacts = artifacts.data.artifacts.filter(artifact => artifact.name === process.env.ARTIFACT_NAME); | ||
| let latestArtifact = null; | ||
|
|
||
| for (const artifact of filteredArtifacts) { | ||
| const run = await github.rest.actions.getWorkflowRun({ | ||
| owner: repo.owner, | ||
| repo: repo.repo, | ||
| run_id: artifact.workflow_run.id, | ||
| }); | ||
|
|
||
| if (run.data.head_branch === process.env.BRANCH_NAME) { | ||
| if (!latestArtifact || new Date(artifact.created_at) > new Date(latestArtifact.created_at)) { | ||
| latestArtifact = artifact; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (latestArtifact) { | ||
| console.log(`Found latest artifact: ${latestArtifact.id}`); | ||
| core.setOutput('artifact_id', latestArtifact.id.toString()); | ||
| return { artifactId: latestArtifact.id.toString()}; | ||
| } else { | ||
| console.log('No matching artifacts found.'); | ||
| core.setOutput('artifact_id', ''); | ||
| return { artifactId: '' }; | ||
| } | ||
| } | ||
|
|
||
| async function downloadArtifact(github, repo, artifactId) { | ||
| const benchmarksDir = process.env.BENCHMARKS_DIR; | ||
| const artifactPath = process.env.ARTIFACT_PATH; | ||
|
|
||
| const download = await github.rest.actions.downloadArtifact({ | ||
| owner: repo.owner, | ||
| repo: repo.repo, | ||
| artifact_id: artifactId, | ||
| archive_format: 'zip', | ||
| }); | ||
|
|
||
| if (!fs.existsSync(benchmarksDir)) { | ||
| fs.mkdirSync(benchmarksDir, { recursive: true }); | ||
| } | ||
| fs.writeFileSync(artifactPath, Buffer.from(download.data)); | ||
| console.log('Artifact downloaded:', artifactPath); | ||
| } | ||
|
|
||
| module.exports = { | ||
| fetchArtifact, | ||
| downloadArtifact | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| name: Scheduled Benchmark Tests | ||
|
|
||
| on: | ||
| schedule: | ||
| # Runs at 00:00 UTC every 90 days | ||
| - cron: '0 0 */90 * *' | ||
|
|
||
| jobs: | ||
| upload_benchmark_artifacts: | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| matrix: | ||
| python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] | ||
|
|
||
| steps: | ||
| - name: Checkout default branch | ||
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #@v4 | ||
|
|
||
| - name: Set up Python ${{ matrix.python-version }} | ||
| uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b #@v5 | ||
| with: | ||
| python-version: ${{ matrix.python-version }} | ||
|
|
||
| - name: Upgrade pip, setuptools, and wheel | ||
| run: | | ||
| pip install --upgrade pip setuptools wheel | ||
|
|
||
| - name: Install dependencies | ||
| run: | | ||
| sudo apt-get update | ||
| pip install wheel # Ensure wheel is installed | ||
| pip install -e .[ci,test] | ||
|
|
||
| - name: Setup GitHub user | ||
| run: | | ||
| git config --global user.name oll-bot | ||
| git config --global user.email developers@openlawlib.org | ||
|
|
||
| - name: Run Benchmark Tests | ||
| run: | | ||
| python -m pytest --benchmark-only --benchmark-json=0001_output.json | ||
|
|
||
| - name: Upload Benchmark Results | ||
| uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 #@v4.6.1 | ||
| with: | ||
| name: benchmark-results-${{ matrix.python-version }} | ||
| path: 0001_output.json |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "renatav/performance-tests": 15 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. question: can we bring this threshold to be lower? Is 15 times slower before it errors out too much?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's 15%. The default is 10%, this is just an example of how to overwrite the default value |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,5 +20,38 @@ If you want to cause failure in the case of regression, also add "–-benchmark- | |
|
|
||
| To compare two already stored results, the standalone command "pytest-benchmark compare" followed by the paths of the files you wish to compare can do that. Unlike the previous method, these files do not need to be stored in any specific folder. | ||
|
|
||
| For further options, see https://pytest-benchmark.readthedocs.io/en/latest/usage.html | ||
|
|
||
| For further options, see https://pytest-benchmark.readthedocs.io/en/latest/usage.html | ||
|
|
||
| ## CI Integration | ||
|
|
||
| The CI workflow is designed to perform benchmark tests on direct pushes to branches. It uses `pytest` with benchmark plugins to assess performance regressions or improvements. To accommodate varying performance expectations across features or branches, a JSON file named `benchmark_thresholds.json` is used to specify custom benchmark thresholds. | ||
|
|
||
| ## How Benchmark Testing Works | ||
|
|
||
| Benchmark tests are run using `pytest` configured to only execute benchmark-related tests: | ||
|
|
||
| - **Flag `--benchmark-only`**: Restricts `pytest` to run only benchmark tests. | ||
| - **Flag `--benchmark-json`**: Outputs the results to a JSON file, allowing for subsequent comparisons. | ||
| - **Flag `--benchmark-compare`**: Compares current benchmarks against the last saved benchmarks. | ||
| - **Flag `--benchmark-compare-fail`**: Specifies a threshold for test failure; if performance degrades beyond this percentage, the test fails. | ||
|
|
||
| These benchmarks help ensure that new code does not introduce significant performance regressions. | ||
|
|
||
| ## Setting Benchmark Thresholds | ||
|
|
||
| The benchmark threshold can be defined for each branch to accommodate specific performance criteria associated with different types of work (e.g., feature development, bug fixes). This threshold is set in the `benchmark_thresholds.json` file. If not set, threshold is set to 10 (10%) by default. | ||
|
|
||
| ### Example `benchmark_thresholds.json`: | ||
|
|
||
| ```json | ||
| { | ||
| "feature/cool-feature": 20, | ||
| "bugfix/urgent-fix": 15 | ||
| } | ||
| ``` | ||
|
|
||
| ## Artifact Handling | ||
|
|
||
| - **Uploading Artifacts**: After benchmarks are run, the resulting `0001_output.json` file is uploaded as an artifact to GitHub Actions, allowing it to be used in future benchmark comparisons. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: adding link to the already uploaded artifacts (from some older GitHub Actions build as an example) would be very useful here |
||
| - **Downloading Artifacts**: In subsequent CI runs, the previously saved benchmark artifact (`0001_output.json`) for the master branch is downloaded before tests are run. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: set-output is getting deprecated. Could we please use the new approach [1]? The deprecation notice is here.
[1] - https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/