Skip to content

Commit 4ae0f93

Browse files
committed
calculate throughput
1 parent 1034ee8 commit 4ae0f93

File tree

2 files changed

+45
-10
lines changed

2 files changed

+45
-10
lines changed

codeflash/models/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ class OriginalCodeBaseline(BaseModel):
380380
line_profile_results: dict
381381
runtime: int
382382
coverage_results: Optional[CoverageData]
383+
async_throughput: Optional[dict[str, int]] = None
383384

384385

385386
class CoverageStatus(Enum):

codeflash/optimization/function_optimizer.py

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,7 +1388,7 @@ def establish_original_code_baseline(
13881388
instrument_codeflash_capture(
13891389
self.function_to_optimize, file_path_to_helper_classes, self.test_cfg.tests_root
13901390
)
1391-
behavioral_results, coverage_results = self.run_and_parse_tests(
1391+
behavioral_results, coverage_results, behavioral_test_results_for_throughput = self.run_and_parse_tests(
13921392
testing_type=TestingMode.BEHAVIOR,
13931393
test_env=test_env,
13941394
test_files=self.test_files,
@@ -1409,6 +1409,8 @@ def establish_original_code_baseline(
14091409
return Failure("Failed to establish a baseline for the original code - bevhavioral tests failed.")
14101410
if not coverage_critic(coverage_results, self.args.test_framework):
14111411
return Failure("The threshold for test coverage was not met.")
1412+
benchmarking_test_results_for_throughput = None
1413+
14121414
if test_framework == "pytest":
14131415
line_profile_results = self.line_profiler_step(
14141416
code_context=code_context, original_helper_code=original_helper_code, candidate_index=0
@@ -1431,7 +1433,7 @@ def establish_original_code_baseline(
14311433
)
14321434

14331435
try:
1434-
benchmarking_results, _ = self.run_and_parse_tests(
1436+
benchmarking_results, _, benchmarking_test_results_for_throughput = self.run_and_parse_tests(
14351437
testing_type=TestingMode.PERFORMANCE,
14361438
test_env=test_env,
14371439
test_files=self.test_files,
@@ -1455,7 +1457,7 @@ def establish_original_code_baseline(
14551457
# * 1.5 to give unittest a bit more time to run
14561458
break
14571459
test_env["CODEFLASH_LOOP_INDEX"] = str(i + 1)
1458-
unittest_loop_results, _ = self.run_and_parse_tests(
1460+
unittest_loop_results, _, _ = self.run_and_parse_tests(
14591461
testing_type=TestingMode.PERFORMANCE,
14601462
test_env=test_env,
14611463
test_files=self.test_files,
@@ -1502,6 +1504,10 @@ def establish_original_code_baseline(
15021504
console.rule()
15031505
logger.debug(f"Total original code runtime (ns): {total_timing}")
15041506

1507+
async_throughput = self.calculate_async_throughput(
1508+
behavioral_test_results_for_throughput, benchmarking_test_results_for_throughput
1509+
)
1510+
15051511
if self.args.benchmark:
15061512
replay_benchmarking_test_results = benchmarking_results.group_by_benchmarks(
15071513
self.total_benchmark_timings.keys(), self.replay_tests_dir, self.project_root
@@ -1517,6 +1523,7 @@ def establish_original_code_baseline(
15171523
runtime=total_timing,
15181524
coverage_results=coverage_results,
15191525
line_profile_results=line_profile_results,
1526+
async_throughput=async_throughput,
15201527
),
15211528
functions_to_remove,
15221529
)
@@ -1564,7 +1571,7 @@ def run_optimized_candidate(
15641571
instrument_codeflash_capture(
15651572
self.function_to_optimize, file_path_to_helper_classes, self.test_cfg.tests_root
15661573
)
1567-
candidate_behavior_results, _ = self.run_and_parse_tests(
1574+
candidate_behavior_results, _, _ = self.run_and_parse_tests(
15681575
testing_type=TestingMode.BEHAVIOR,
15691576
test_env=test_env,
15701577
test_files=self.test_files,
@@ -1610,7 +1617,7 @@ def run_optimized_candidate(
16101617
)
16111618

16121619
try:
1613-
candidate_benchmarking_results, _ = self.run_and_parse_tests(
1620+
candidate_benchmarking_results, _, _ = self.run_and_parse_tests(
16141621
testing_type=TestingMode.PERFORMANCE,
16151622
test_env=test_env,
16161623
test_files=self.test_files,
@@ -1643,7 +1650,7 @@ def run_optimized_candidate(
16431650
# * 1.5 to give unittest a bit more time to run
16441651
break
16451652
test_env["CODEFLASH_LOOP_INDEX"] = str(i + 1)
1646-
unittest_loop_results, cov = self.run_and_parse_tests(
1653+
unittest_loop_results, cov, _ = self.run_and_parse_tests(
16471654
testing_type=TestingMode.PERFORMANCE,
16481655
test_env=test_env,
16491656
test_files=self.test_files,
@@ -1695,7 +1702,7 @@ def run_and_parse_tests(
16951702
code_context: CodeOptimizationContext | None = None,
16961703
unittest_loop_index: int | None = None,
16971704
line_profiler_output_file: Path | None = None,
1698-
) -> tuple[TestResults | dict, CoverageData | None]:
1705+
) -> tuple[TestResults | dict, CoverageData | None, TestResults | None]:
16991706
coverage_database_file = None
17001707
coverage_config_file = None
17011708
try:
@@ -1741,7 +1748,7 @@ def run_and_parse_tests(
17411748
logger.exception(
17421749
f"Error running tests in {', '.join(str(f) for f in test_files.test_files)}.\nTimeout Error"
17431750
)
1744-
return TestResults(), None
1751+
return TestResults(), None, None
17451752
if run_result.returncode != 0 and testing_type == TestingMode.BEHAVIOR:
17461753
logger.debug(
17471754
f"Nonzero return code {run_result.returncode} when running tests in "
@@ -1769,9 +1776,11 @@ def run_and_parse_tests(
17691776
coverage_database_file=coverage_database_file,
17701777
coverage_config_file=coverage_config_file,
17711778
)
1779+
# Return the test results for async throughput calculation
1780+
return results, coverage_results, results if isinstance(results, TestResults) else None
17721781
else:
17731782
results, coverage_results = parse_line_profile_results(line_profiler_output_file=line_profiler_output_file)
1774-
return results, coverage_results
1783+
return results, coverage_results, None
17751784

17761785
def submit_test_generation_tasks(
17771786
self,
@@ -1822,6 +1831,31 @@ def get_test_env(
18221831
test_env["PYTHONPATH"] += os.pathsep + str(self.args.project_root)
18231832
return test_env
18241833

1834+
def calculate_async_throughput(
1835+
self, behavioral_test_results: TestResults | None, benchmarking_test_results: TestResults | None
1836+
) -> dict[str, int] | None:
1837+
if not self.function_to_optimize.is_async:
1838+
return None
1839+
1840+
from codeflash.verification.parse_test_output import calculate_function_throughput_from_stdout
1841+
1842+
all_stdout = ""
1843+
1844+
for test_results in [behavioral_test_results, benchmarking_test_results]:
1845+
if test_results:
1846+
for result in test_results.test_results:
1847+
if result.stdout:
1848+
all_stdout += result.stdout
1849+
1850+
if not all_stdout:
1851+
return None
1852+
1853+
function_throughput = calculate_function_throughput_from_stdout(
1854+
all_stdout, self.function_to_optimize.function_name
1855+
)
1856+
1857+
return {self.function_to_optimize.function_name: function_throughput} if function_throughput > 0 else None
1858+
18251859
def line_profiler_step(
18261860
self, code_context: CodeOptimizationContext, original_helper_code: dict[Path, str], candidate_index: int
18271861
) -> dict:
@@ -1830,7 +1864,7 @@ def line_profiler_step(
18301864
codeflash_loop_index=0, codeflash_test_iteration=candidate_index, codeflash_tracer_disable=1
18311865
)
18321866
line_profiler_output_file = add_decorator_imports(self.function_to_optimize, code_context)
1833-
line_profile_results, _ = self.run_and_parse_tests(
1867+
line_profile_results, _, _ = self.run_and_parse_tests(
18341868
testing_type=TestingMode.LINE_PROFILE,
18351869
test_env=test_env,
18361870
test_files=self.test_files,

0 commit comments

Comments
 (0)