Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ __pycache__/
logger/
dataset/
data/
profiling/results/
#Ignore vscode AI rules
.*/
.*
!.env.example
!.env.example
15 changes: 15 additions & 0 deletions profiling/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Template profiling

Profile a template from the repository root:

```bash
python profiling/profile_template.py <template>
```

The command runs the template with Python's built-in `cProfile` and writes the
binary profile plus a cumulative-time report to
`profiling/results/<template>/`.

Install the template's dependencies first. For long-running templates, reduce
the workload in its `fenn.yaml` before profiling and restore it afterwards.
Generated profiles are environment-specific and are not committed.
50 changes: 50 additions & 0 deletions profiling/profile_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import argparse
import pstats
import subprocess
import sys
from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]


def main() -> None:
parser = argparse.ArgumentParser(description="Profile a fenn template.")
parser.add_argument("template", help="Template directory to profile")
parser.add_argument("--limit", type=int, default=25, help="Rows in the report")
args = parser.parse_args()

template = ROOT / args.template
entrypoint = template / "main.py"
if not entrypoint.is_file() or template.parent != ROOT:
parser.error(f"unknown template: {args.template}")

output_dir = ROOT / "profiling" / "results" / args.template
output_dir.mkdir(parents=True, exist_ok=True)
profile_path = output_dir / "cprofile.prof"
report_path = output_dir / "cprofile.txt"

subprocess.run(
[
sys.executable,
"-m",
"cProfile",
"-o",
str(profile_path),
entrypoint.name,
],
cwd=template,
check=True,
)

with report_path.open("w", encoding="utf-8") as report:
pstats.Stats(str(profile_path), stream=report).strip_dirs().sort_stats(
"cumulative"
).print_stats(args.limit)

print(f"Profile: {profile_path}")
print(f"Report: {report_path}")


if __name__ == "__main__":
main()