Skip to content
New issue

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

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

Already on GitHub? # to your account

[REF-1682][REF-1683][REF-1684][REF-2283]Benchmark reflex package size and .web folder #2880

Merged
merged 52 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
d834590
remove codspeed.yml
ElijahAhianyo Mar 19, 2024
dce878e
test upload job
ElijahAhianyo Mar 19, 2024
de4ad3a
minor edits to get upload job working
ElijahAhianyo Mar 19, 2024
c38c513
perhaps this works
ElijahAhianyo Mar 19, 2024
afd7316
upload needs relex-install-size
ElijahAhianyo Mar 19, 2024
6407e34
retrigger pipeline
ElijahAhianyo Mar 19, 2024
04cb812
test only on ubuntu
ElijahAhianyo Mar 19, 2024
ea87133
change to save to db directly
ElijahAhianyo Mar 19, 2024
c951b5f
oops
ElijahAhianyo Mar 19, 2024
edea54a
size benchmarks
ElijahAhianyo Mar 19, 2024
d9d2e41
.web for counter
ElijahAhianyo Mar 20, 2024
4c03202
its timeout-minutes
ElijahAhianyo Mar 20, 2024
8be31ed
se integration.sh to run and kill process
ElijahAhianyo Mar 20, 2024
5c55274
install psycopg2
ElijahAhianyo Mar 20, 2024
cd608b4
move .web runs to integration_tests.yml to save runners
ElijahAhianyo Mar 20, 2024
603be7a
fix measurement-type for reflex-web
ElijahAhianyo Mar 20, 2024
1ff4036
add database url to env
ElijahAhianyo Mar 20, 2024
ae9c6db
psycopg2
ElijahAhianyo Mar 20, 2024
3cbc9e0
test run ids
ElijahAhianyo Mar 20, 2024
e292174
commit sha gets the job done
ElijahAhianyo Mar 20, 2024
ff1ae50
refactor
ElijahAhianyo Mar 20, 2024
ecb86f8
add more matrices
ElijahAhianyo Mar 20, 2024
7ece8ac
move reflex package size to integration_test.yml
ElijahAhianyo Mar 20, 2024
1a0b763
fix venv path
ElijahAhianyo Mar 20, 2024
d3ecec4
test fix
ElijahAhianyo Mar 20, 2024
72eba01
test fix
ElijahAhianyo Mar 20, 2024
844349d
use hyphen
ElijahAhianyo Mar 20, 2024
c663e70
testing reflex build size
ElijahAhianyo Mar 20, 2024
087f667
ls for temp debug
ElijahAhianyo Mar 20, 2024
71e3e20
fix typo in command
ElijahAhianyo Mar 20, 2024
d5e4783
possible fix
ElijahAhianyo Mar 20, 2024
7d01b33
possible fix for windows
ElijahAhianyo Mar 20, 2024
d34c07d
remove dead code
ElijahAhianyo Mar 20, 2024
5a9ebc6
remove dead code
ElijahAhianyo Mar 20, 2024
582cdb7
remove unwanted comments
ElijahAhianyo Mar 20, 2024
9c04cca
refactor
ElijahAhianyo Mar 20, 2024
0a3dc4c
rebase on main
ElijahAhianyo Mar 21, 2024
4a7ca35
pr_title
ElijahAhianyo Mar 21, 2024
84cecd9
remove pr_title from args
ElijahAhianyo Mar 21, 2024
59fb90b
debug
ElijahAhianyo Mar 21, 2024
dfbab73
should work now
ElijahAhianyo Mar 21, 2024
78cb0c8
precommit fix
ElijahAhianyo Mar 21, 2024
23e6dae
print out package size for
ElijahAhianyo Mar 22, 2024
36000da
add shell
ElijahAhianyo Mar 22, 2024
95670c7
test
ElijahAhianyo Mar 22, 2024
b07fc2d
trying again
ElijahAhianyo Mar 22, 2024
4aaf234
dont use cached poetry to have accurate measurement of deps
ElijahAhianyo Mar 22, 2024
d982658
remove reflex deps calculation step from integration job
ElijahAhianyo Mar 22, 2024
62de909
fix script path
ElijahAhianyo Mar 22, 2024
4053bc9
precommit fix
ElijahAhianyo Mar 22, 2024
fa4ad9d
no real difference on different python versions so use 3.11.5
ElijahAhianyo Mar 22, 2024
59c9b68
remove ls keyword
ElijahAhianyo Mar 22, 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
77 changes: 71 additions & 6 deletions .github/workflows/benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ env:
TELEMETRY_ENABLED: false
NODE_OPTIONS: '--max_old_space_size=4096'
DATABASE_URL: ${{ secrets.DATABASE_URL }}
PR_TITLE: ${{ github.event.pull_request.title }}


jobs:
reflex-web:
Expand Down Expand Up @@ -63,16 +65,15 @@ jobs:
run: |
# Check that npm is home
npm -v
poetry run bash scripts/benchmarks.sh ./reflex-web prod
poetry run bash scripts/benchmarks/benchmarks.sh ./reflex-web prod
env:
LHCI_GITHUB_APP_TOKEN: $
- name: Run Benchmarks
# Only run if the database creds are available in this context.
if: ${{ env.DATABASE_URL }}
run: poetry run python scripts/lighthouse_score_upload.py "$GITHUB_SHA" ./integration/benchmarks/.lighthouseci
run: poetry run python scripts/benchmarks/lighthouse_score_upload.py "$GITHUB_SHA" ./integration/benchmarks/.lighthouseci
env:
GITHUB_SHA: ${{ github.sha }}
PR_TITLE: ${{ github.event.pull_request.title }}

simple-apps-benchmarks:
env:
Expand Down Expand Up @@ -119,11 +120,75 @@ jobs:
- name: Upload benchmark results
# Only run if the database creds are available in this context.
if: ${{ env.DATABASE_URL }}
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run:
poetry run python scripts/simple_app_benchmark_upload.py --os "${{ matrix.os }}"
poetry run python scripts/benchmarks/simple_app_benchmark_upload.py --os "${{ matrix.os }}"
--python-version "${{ matrix.python-version }}" --commit-sha "${{ github.sha }}"
--benchmark-json "${{ env.OUTPUT_FILE }}"
--db-url "${{ env.DATABASE_URL }}" --branch-name "${{ github.head_ref || github.ref_name }}"
--event-type "${{ github.event_name }}" --actor "${{ github.actor }}" --pr-id "${{ github.event.pull_request.id }}"

reflex-build-size:
timeout-minutes: 30
strategy:
# Prioritize getting more information out of the workflow (even if something fails)
fail-fast: false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup_build_env
with:
python-version: 3.11.5
run-poetry-install: true
create-venv-at-path: .venv
- name: Install additional dependencies for DB access
run: poetry run pip install psycopg2-binary
- name: Build reflex
run: |
poetry build
- name: Upload benchmark results
# Only run if the database creds are available in this context.
if: ${{ env.DATABASE_URL }}
run: poetry run python scripts/benchmarks/benchmark_reflex_size.py --os ubuntu-latest
--python-version 3.11.5 --commit-sha "${{ github.sha }}" --pr-id "${{ github.event.pull_request.id }}"
--db-url "${{ env.DATABASE_URL }}" --branch-name "${{ github.head_ref || github.ref_name }}"
--measurement-type "reflex-build" --path ./dist

reflex-plus-dependency-size:
timeout-minutes: 30
strategy:
# Prioritize getting more information out of the workflow (even if something fails)
fail-fast: false
matrix:
# Show OS combos first in GUI
os: [ ubuntu-latest, windows-latest, macos-latest ]
python-version: [ '3.11.5']

runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4

- name: Install Poetry
uses: snok/install-poetry@v1
with:
version : 1.3.1
virtualenvs-create: true
virtualenvs-in-project: true
virtualenvs-path: .venv

- name: Run poetry install
shell: bash
run: |
python -m venv .venv
source .venv/*/activate
poetry install --without dev --no-interaction --no-root

- name: Install additional dependencies for DB access
run: poetry run pip install psycopg2-binary

- if: ${{ env.DATABASE_URL }}
name: calculate and upload size
run: poetry run python scripts/benchmarks/benchmark_reflex_size.py --os "${{ matrix.os }}"
--python-version "${{ matrix.python-version }}" --commit-sha "${{ github.sha }}"
--pr-id "${{ github.event.pull_request.id }}" --db-url "${{ env.DATABASE_URL }}"
--branch-name "${{ github.head_ref || github.ref_name }}"
--measurement-type "reflex-package" --path ./.venv
23 changes: 21 additions & 2 deletions .github/workflows/integration_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ env:
PYTHONIOENCODING: 'utf8'
TELEMETRY_ENABLED: false
NODE_OPTIONS: '--max_old_space_size=4096'
DATABASE_URL: ${{ secrets.DATABASE_URL }}
PR_TITLE: ${{ github.event.pull_request.title }}


jobs:
example-counter:
Expand Down Expand Up @@ -60,17 +63,17 @@ jobs:
python-version: ${{ matrix.python-version }}
run-poetry-install: true
create-venv-at-path: .venv

- name: Clone Reflex Examples Repo
uses: actions/checkout@v4
with:
repository: reflex-dev/reflex-examples
path: reflex-examples

- name: Install requirements for counter example
working-directory: ./reflex-examples/counter
run: |
poetry run pip install -r requirements.txt
- name: Install additional dependencies for DB access
run: poetry run pip install psycopg2-binary
- name: Check export --backend-only before init for counter example
working-directory: ./reflex-examples/counter
run: |
Expand All @@ -91,6 +94,13 @@ jobs:
# Check that npm is home
npm -v
poetry run bash scripts/integration.sh ./reflex-examples/counter dev
- name: Measure and upload .web size
if: ${{ env.DATABASE_URL }}
run: poetry run python scripts/benchmarks/benchmark_reflex_size.py --os "${{ matrix.os }}"
--python-version "${{ matrix.python-version }}" --commit-sha "${{ github.sha }}"
--pr-id "${{ github.event.pull_request.id }}" --db-url "${{ env.DATABASE_URL }}"
--branch-name "${{ github.head_ref || github.ref_name }}"
--measurement-type "counter-app-dot-web" --path ./reflex-examples/counter/.web

reflex-web:
strategy:
Expand Down Expand Up @@ -121,6 +131,8 @@ jobs:
- name: Install Requirements for reflex-web
working-directory: ./reflex-web
run: poetry run pip install -r requirements.txt
- name: Install additional dependencies for DB access
run: poetry run pip install psycopg2-binary
- name: Init Website for reflex-web
working-directory: ./reflex-web
run: poetry run reflex init
Expand All @@ -129,3 +141,10 @@ jobs:
# Check that npm is home
npm -v
poetry run bash scripts/integration.sh ./reflex-web prod
- name: Measure and upload .web size
if: ${{ env.DATABASE_URL }}
run: poetry run python scripts/benchmarks/benchmark_reflex_size.py --os "${{ matrix.os }}"
--python-version "${{ matrix.python-version }}" --commit-sha "${{ github.sha }}"
--pr-id "${{ github.event.pull_request.id }}"
--db-url "${{ env.DATABASE_URL }}" --branch-name "${{ github.head_ref || github.ref_name }}"
--measurement-type "reflex-web-dot-web" --path ./reflex-web/.web
206 changes: 206 additions & 0 deletions scripts/benchmarks/benchmark_reflex_size.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
"""Checks the size of a specific directory and uploads result."""
import argparse
import os
import subprocess
from datetime import datetime

import psycopg2


def get_directory_size(directory):
"""Get the size of a directory in bytes.

Args:
directory: The directory to check.

Returns:
The size of the dir in bytes.
"""
total_size = 0
for dirpath, _, filenames in os.walk(directory):
for f in filenames:
fp = os.path.join(dirpath, f)
total_size += os.path.getsize(fp)
return total_size


def get_python_version(venv_path, os_name):
"""Get the python version of python in a virtual env.

Args:
venv_path: Path to virtual environment.
os_name: Name of os.

Returns:
The python version.
"""
python_executable = (
os.path.join(venv_path, "bin", "python")
if "windows" not in os_name
else os.path.join(venv_path, "Scripts", "python.exe")
)
try:
output = subprocess.check_output(
[python_executable, "--version"], stderr=subprocess.STDOUT
)
python_version = output.decode("utf-8").strip().split()[1]
return ".".join(python_version.split(".")[:-1])
except subprocess.CalledProcessError:
return None


def get_package_size(venv_path, os_name):
"""Get the size of a specified package.

Args:
venv_path: The path to the venv.
os_name: Name of os.

Returns:
The total size of the package in bytes.

Raises:
ValueError: when venv does not exist or python version is None.
"""
python_version = get_python_version(venv_path, os_name)
if python_version is None:
raise ValueError("Error: Failed to determine Python version.")

is_windows = "windows" in os_name

full_path = (
["lib", f"python{python_version}", "site-packages"]
if not is_windows
else ["Lib", "site-packages"]
)

package_dir = os.path.join(venv_path, *full_path)
if not os.path.exists(package_dir):
raise ValueError(
"Error: Virtual environment does not exist or is not activated."
)

total_size = get_directory_size(package_dir)
return total_size


def insert_benchmarking_data(
db_connection_url: str,
os_type_version: str,
python_version: str,
measurement_type: str,
commit_sha: str,
pr_title: str,
branch_name: str,
pr_id: str,
path: str,
):
"""Insert the benchmarking data into the database.

Args:
db_connection_url: The URL to connect to the database.
os_type_version: The OS type and version to insert.
python_version: The Python version to insert.
measurement_type: The type of metric to measure.
commit_sha: The commit SHA to insert.
pr_title: The PR title to insert.
branch_name: The name of the branch.
pr_id: The id of the PR.
path: The path to the dir or file to check size.
"""
if measurement_type == "reflex-package":
size = get_package_size(path, os_type_version)
else:
size = get_directory_size(path)

# Get the current timestamp
current_timestamp = datetime.now()

# Connect to the database and insert the data
with psycopg2.connect(db_connection_url) as conn, conn.cursor() as cursor:
insert_query = """
INSERT INTO size_benchmarks (os, python_version, commit_sha, created_at, pr_title, branch_name, pr_id, measurement_type, size)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s);
"""
cursor.execute(
insert_query,
(
os_type_version,
python_version,
commit_sha,
current_timestamp,
pr_title,
branch_name,
pr_id,
measurement_type,
round(
size / (1024 * 1024), 3
), # save size in mb and round to 3 places.
),
)
# Commit the transaction
conn.commit()


def main():
"""Runs the benchmarks and inserts the results."""
parser = argparse.ArgumentParser(description="Run benchmarks and process results.")
parser.add_argument(
"--os", help="The OS type and version to insert into the database."
)
parser.add_argument(
"--python-version", help="The Python version to insert into the database."
)
parser.add_argument(
"--commit-sha", help="The commit SHA to insert into the database."
)
parser.add_argument(
"--db-url",
help="The URL to connect to the database.",
required=True,
)
parser.add_argument(
"--pr-title",
help="The PR title to insert into the database.",
)
parser.add_argument(
"--branch-name",
help="The current branch",
required=True,
)
parser.add_argument(
"--pr-id",
help="The pr id",
required=True,
)
parser.add_argument(
"--measurement-type",
help="The type of metric to be checked.",
required=True,
)
parser.add_argument(
"--path",
help="the current path to check size.",
required=True,
)
args = parser.parse_args()

# Get the PR title from env or the args. For the PR merge or push event, there is no PR title, leaving it empty.
pr_title = args.pr_title or os.getenv("PR_TITLE", "")

# Insert the data into the database
insert_benchmarking_data(
db_connection_url=args.db_url,
os_type_version=args.os,
python_version=args.python_version,
measurement_type=args.measurement_type,
commit_sha=args.commit_sha,
pr_title=pr_title,
branch_name=args.branch_name,
pr_id=args.pr_id,
path=args.path,
)


if __name__ == "__main__":
main()
File renamed without changes.
Loading