Skip to content

Commit

Permalink
feat(profiling): Add examples and setup
Browse files Browse the repository at this point in the history
  • Loading branch information
piotrgredowski committed Sep 19, 2024
1 parent 2e0b14c commit d953762
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ htmlcov
.venv

.DS_Store

*.profile.*
*results.txt
7 changes: 7 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": true
},
{
"name": "Profile current file",
"type": "debugpy",
"request": "launch",
"module": "cProfile",
"args": ["-o", "profile_data.prof", "${file}"]
}
]
}
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ For talks, presentations, workshops, demos.
```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.lock -r requirements-dev.lock
pip install pip --upgrade
pip install -e ".[dev]"
```

### Option 2
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,6 @@ dev-dependencies = [
"ipython>=8.12.2",
"pytest-cov>=5.0.0",
"pytest-xdist>=3.6.1",
"pyinstrument>=4.7.3",
"snakeviz>=2.2.0",
]
33 changes: 33 additions & 0 deletions src/profiling/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Profiling Python code

## Setup

```bash
python3 -m venv .venv
source .venv/bin/activate
pip install pip --upgrade
pip install pyinstrument snakeviz
```

## Sources

- https://docs.python.org/3/library/timeit.html
- https://docs.python.org/3/library/profile.html
- https://pyinstrument.readthedocs.io/en/latest/home.html
- https://realpython.com/python-profiling/#pyinstrument-take-snapshots-of-the-call-stack

## Profiling with pyinstrument

```bash
python -m pyinstrument --color --renderer=html --use-timing-thread --show-all --timeline --outfile _pyinstrument.profile.html src/profiling/primes.py
python -m pyinstrument --color --renderer=html --use-timing-thread --show-all --outfile _pyinstrument.profile.html src/profiling/primes.py
python -m pyinstrument --color --renderer=html --use-timing-thread --show-all --timeline src/profiling/primes.py
python -m pyinstrument src/profiling/primes.py
```

## Profiling with cProfile

```bash
python -m cProfile -o _profile_data.profile.pstats src/profiling/primes.py
python -m snakeviz _profile_data.profile.pstats
```
Empty file added src/profiling/__init__.py
Empty file.
93 changes: 93 additions & 0 deletions src/profiling/primes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import random
import time

RESULTS_FILE_NAME = "_results.txt"
UNIQUE_RESULTS_FILE_NAME = "_unique_results.txt"


def _slow_sort(arr):
n = len(arr)
for i in range(n):
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr


def sort(*args, **kwargs):
return _slow_sort(*args, **kwargs)


def _slow_prime_check(n):
if n < 2:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False
time.sleep(0.01)
return True


def prime_check(*args, **kwargs):
return _slow_prime_check(*args, **kwargs)


def _slow_make_unique(data):
unique = []
for item in data:
if item not in unique:
unique.append(item)
return unique


def make_unique(*args, **kwargs):
return _slow_make_unique(*args, **kwargs)


def _slow_save_items(results, file_name):
for item in results:
with open(file_name, "a") as f:
f.write(str(item) + "\n")


def save_items(*args, **kwargs):
return _slow_save_items(*args, **kwargs)


def process_data(data):
primes = []
result = []
for item in data:
if prime_check(item):
result.append(f"* {str(item).rjust(6)} is prime")
primes.append(item)
else:
result.append(f" {str(item).rjust(6)}")

save_items(result, file_name=RESULTS_FILE_NAME)
save_items(make_unique(sort(primes)), file_name=UNIQUE_RESULTS_FILE_NAME)

return result


def main():
with open(RESULTS_FILE_NAME, "w") as f:
f.write("")
with open(UNIQUE_RESULTS_FILE_NAME, "w") as f:
f.write("")

number = 1000
data = [random.randint(1, number) for _ in range(number)]

start_time = time.time()

sorted_data = sort(data)
processed_data = process_data(sorted_data)

end_time = time.time()

print(f"Time taken: {end_time - start_time:.2f}s")


if __name__ == "__main__":
main()
102 changes: 102 additions & 0 deletions uv.lock

Large diffs are not rendered by default.

0 comments on commit d953762

Please sign in to comment.