Skip to content

Commit 938073b

Browse files
authored
Merge pull request PSLmodels#1049 from jdebacker/dask-performance-benchmarks
Merging
2 parents ef6695e + 689bb83 commit 938073b

10 files changed

Lines changed: 2197 additions & 14 deletions

File tree

.github/workflows/build_and_test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
shell: bash -l {0}
5151
working-directory: ./
5252
run: |
53-
python -m pytest -m "not local" --cov=./ --cov-report=xml
53+
python -m pytest -m "not local and not benchmark" --cov=./ --cov-report=xml
5454
- name: Upload coverage to Codecov
5555
if: matrix.os == 'ubuntu-latest' && contains(github.repository, 'PSLmodels/OG-Core')
5656
uses: codecov/codecov-action@v4

CHANGELOG.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,37 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88

9+
## [0.14.8] - 2025-08-26 12:00:00
10+
11+
### Added
12+
13+
- Adds a complete benchmark suite for measuring and optimizing Dask performance in OG-Core, with particular focus on Windows performance issues.
14+
- New and updated files:
15+
- tests/test_dask_benchmarks.py: Mock benchmark tests with synthetic workloads
16+
- tests/test_real_txfunc_benchmarks.py: Real-world tax function benchmarks
17+
- tests/run_benchmarks.py: Automated benchmark runner with reporting
18+
- tests/BENCHMARK_README.md: Comprehensive documentation and usage guide
19+
- pytest.ini: Updated with benchmark test markers
20+
- Key features:
21+
- Platform-specific optimization tests (Windows, macOS, Linux)
22+
- Memory usage and compute time benchmarking
23+
- Baseline establishment and performance regression detection
24+
- Comparison of different Dask schedulers and client configurations
25+
- Real tax function estimation performance measurement
26+
- Automated identification of optimal Dask settings per platform
27+
- Benefits:
28+
- Establishes performance baselines before optimization work
29+
- Identifies Windows-specific Dask performance bottlenecks
30+
- Provides automated regression detection for future changes
31+
- Enables data-driven optimization decisions
32+
- Supports continuous performance monitoring
33+
- Usage:
34+
- `python tests/run_benchmarks.py # Run all benchmarks`
35+
- `python tests/run_benchmarks.py --quick # Quick benchmarks only`
36+
- `python tests/run_benchmarks.py --save-baseline # Save performance baseline`
37+
- `python tests/run_benchmarks.py --compare-baseline # Compare against baseline`
38+
- 🤖 Generated with help from Claude Code
39+
940
## [0.14.7] - 2025-08-21 17:00:00
1041

1142
### Added
@@ -409,6 +440,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
409440
- Any earlier versions of OG-USA can be found in the [`OG-Core`](https://github.com/PSLmodels/OG-Core) repository [release history](https://github.com/PSLmodels/OG-Core/releases) from [v.0.6.4](https://github.com/PSLmodels/OG-Core/releases/tag/v0.6.4) (Jul. 20, 2021) or earlier.
410441

411442

443+
[0.14.8]: https://github.com/PSLmodels/OG-Core/compare/v0.14.7...v0.14.8
412444
[0.14.7]: https://github.com/PSLmodels/OG-Core/compare/v0.14.6...v0.14.7
413445
[0.14.6]: https://github.com/PSLmodels/OG-Core/compare/v0.14.5...v0.14.6
414446
[0.14.5]: https://github.com/PSLmodels/OG-Core/compare/v0.14.4...v0.14.5

ogcore/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@
2020
from ogcore.txfunc import *
2121
from ogcore.utils import *
2222

23-
__version__ = "0.14.7"
23+
__version__ = "0.14.8"

ogcore/household.py

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@
77
# Packages
88
import numpy as np
99
from ogcore import tax, utils
10+
import logging
11+
12+
# Configure logging
13+
VERBOSE = False
14+
log_level = logging.INFO if VERBOSE else logging.WARNING
15+
logging.basicConfig(
16+
level=log_level, format="%(message)s" # Only show the message itself
17+
)
1018

1119
"""
1220
------------------------------------------------------------------------
@@ -764,28 +772,30 @@ def constraint_checker_SS(bssmat, nssmat, cssmat, ltilde):
764772
Warnings: if constraints are violated, warnings printed
765773
766774
"""
767-
print("Checking constraints on capital, labor, and consumption.")
775+
logging.info("Checking constraints on capital, labor, and consumption.")
768776

769777
if (bssmat < 0).any():
770-
print("\tWARNING: There is negative capital stock")
778+
logging.info("\tWARNING: There is negative capital stock")
771779
flag2 = False
772780
if (nssmat < 0).any():
773-
print(
781+
logging.info(
774782
"\tWARNING: Labor supply violates nonnegativity ", "constraints."
775783
)
776784
flag2 = True
777785
if (nssmat > ltilde).any():
778-
print("\tWARNING: Labor supply violates the ltilde constraint.")
786+
logging.info("\tWARNING: Labor supply violates the ltilde constraint.")
779787
flag2 = True
780788
if flag2 is False:
781-
print(
789+
logging.info(
782790
"\tThere were no violations of the constraints on labor",
783791
" supply.",
784792
)
785793
if (cssmat < 0).any():
786-
print("\tWARNING: Consumption violates nonnegativity", " constraints.")
794+
logging.info(
795+
"\tWARNING: Consumption violates nonnegativity", " constraints."
796+
)
787797
else:
788-
print(
798+
logging.info(
789799
"\tThere were no violations of the constraints on", " consumption."
790800
)
791801

@@ -810,22 +820,22 @@ def constraint_checker_TPI(b_dist, n_dist, c_dist, t, ltilde):
810820
811821
"""
812822
if (b_dist <= 0).any():
813-
print(
823+
logging.info(
814824
"\tWARNING: Aggregate capital is less than or equal to ",
815825
"zero in period %.f." % t,
816826
)
817827
if (n_dist < 0).any():
818-
print(
828+
logging.info(
819829
"\tWARNING: Labor supply violates nonnegativity",
820830
" constraints in period %.f." % t,
821831
)
822832
if (n_dist > ltilde).any():
823-
print(
833+
logging.info(
824834
"\tWARNING: Labor suppy violates the ltilde constraint",
825835
" in period %.f." % t,
826836
)
827837
if (c_dist < 0).any():
828-
print(
838+
logging.info(
829839
"\tWARNING: Consumption violates nonnegativity",
830840
" constraints in period %.f." % t,
831841
)

pytest.ini

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,10 @@ testpaths =
55
./tests
66
markers =
77
local: marks tests that run locally and not on GH Actions (mostly due to run time)
8+
benchmark: marks tests that measure performance and memory usage
9+
distributed: marks tests that use distributed Dask clients
10+
memory: marks tests focused on memory usage measurement
11+
performance: marks tests focused on compute time measurement
12+
slow: marks tests that take longer to run
13+
real: marks tests using real OG-Core tax function code
14+
platform: marks tests for platform-specific optimization

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setuptools.setup(
77
name="ogcore",
8-
version="0.14.7",
8+
version="0.14.8",
99
author="Jason DeBacker and Richard W. Evans",
1010
license="CC0 1.0 Universal (CC0 1.0) Public Domain Dedication",
1111
description="A general equilibrium overlapping generations model for fiscal policy analysis",

0 commit comments

Comments
 (0)