Skip to content

Commit 58f088c

Browse files
committed
throughput
1 parent ce1445c commit 58f088c

File tree

1 file changed

+59
-7
lines changed

1 file changed

+59
-7
lines changed

codeflash/optimization/function_optimizer.py

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,20 @@
8484
TestType,
8585
)
8686
from codeflash.result.create_pr import check_create_pr, existing_tests_source_for
87-
from codeflash.result.critic import coverage_critic, performance_gain, quantity_of_tests_critic, speedup_critic
87+
from codeflash.result.critic import (
88+
coverage_critic,
89+
performance_gain,
90+
quantity_of_tests_critic,
91+
speedup_critic,
92+
throughput_gain,
93+
)
8894
from codeflash.result.explanation import Explanation
8995
from codeflash.telemetry.posthog_cf import ph
9096
from codeflash.verification.concolic_testing import generate_concolic_tests
9197
from codeflash.verification.equivalence import compare_test_results
9298
from codeflash.verification.instrument_codeflash_capture import instrument_codeflash_capture
9399
from codeflash.verification.parse_line_profile_test_output import parse_line_profile_results
94-
from codeflash.verification.parse_test_output import parse_test_results
100+
from codeflash.verification.parse_test_output import calculate_function_throughput_from_test_results, parse_test_results
95101
from codeflash.verification.test_runner import run_behavioral_tests, run_benchmarking_tests, run_line_profile_tests
96102
from codeflash.verification.verification_utils import get_test_file_path
97103
from codeflash.verification.verifier import generate_tests
@@ -582,7 +588,11 @@ def determine_best_candidate(
582588
tree = Tree(f"Candidate #{candidate_index} - Runtime Information ⌛")
583589
benchmark_tree = None
584590
if speedup_critic(
585-
candidate_result, original_code_baseline.runtime, best_runtime_until_now=None
591+
candidate_result,
592+
original_code_baseline.runtime,
593+
best_runtime_until_now=None,
594+
original_async_throughput=original_code_baseline.async_throughput,
595+
best_throughput_until_now=None,
586596
) and quantity_of_tests_critic(candidate_result):
587597
tree.add("This candidate is faster than the original code. 🚀") # TODO: Change this description
588598
tree.add(f"Original summed runtime: {humanize_runtime(original_code_baseline.runtime)}")
@@ -597,7 +607,6 @@ def determine_best_candidate(
597607
original_code_baseline.async_throughput is not None
598608
and candidate_result.async_throughput is not None
599609
):
600-
from codeflash.result.critic import throughput_gain
601610
throughput_gain_value = throughput_gain(
602611
original_throughput=original_code_baseline.async_throughput,
603612
optimized_throughput=candidate_result.async_throughput,
@@ -669,7 +678,6 @@ def determine_best_candidate(
669678
original_code_baseline.async_throughput is not None
670679
and candidate_result.async_throughput is not None
671680
):
672-
from codeflash.result.critic import throughput_gain
673681
throughput_gain_value = throughput_gain(
674682
original_throughput=original_code_baseline.async_throughput,
675683
optimized_throughput=candidate_result.async_throughput,
@@ -1301,6 +1309,8 @@ def find_and_process_best_optimization(
13011309
function_name=function_to_optimize_qualified_name,
13021310
file_path=self.function_to_optimize.file_path,
13031311
benchmark_details=processed_benchmark_info.benchmark_details if processed_benchmark_info else None,
1312+
original_async_throughput=original_code_baseline.async_throughput,
1313+
best_async_throughput=best_optimization.async_throughput,
13041314
)
13051315

13061316
self.replace_function_and_helpers_with_optimized_code(
@@ -1383,6 +1393,23 @@ def process_review(
13831393
original_runtimes_all=original_runtime_by_test,
13841394
optimized_runtimes_all=optimized_runtime_by_test,
13851395
)
1396+
original_throughput_str = None
1397+
optimized_throughput_str = None
1398+
throughput_improvement_str = None
1399+
1400+
if (
1401+
self.function_to_optimize.is_async
1402+
and original_code_baseline.async_throughput is not None
1403+
and best_optimization.async_throughput is not None
1404+
):
1405+
original_throughput_str = f"{original_code_baseline.async_throughput} operations/second"
1406+
optimized_throughput_str = f"{best_optimization.async_throughput} operations/second"
1407+
throughput_improvement_value = throughput_gain(
1408+
original_throughput=original_code_baseline.async_throughput,
1409+
optimized_throughput=best_optimization.async_throughput,
1410+
)
1411+
throughput_improvement_str = f"{throughput_improvement_value * 100:.1f}%"
1412+
13861413
new_explanation_raw_str = self.aiservice_client.get_new_explanation(
13871414
source_code=code_context.read_writable_code.flat,
13881415
dependency_code=code_context.read_only_context_code,
@@ -1396,6 +1423,9 @@ def process_review(
13961423
annotated_tests=generated_tests_str,
13971424
optimization_id=best_optimization.candidate.optimization_id,
13981425
original_explanation=best_optimization.candidate.explanation,
1426+
original_throughput=original_throughput_str,
1427+
optimized_throughput=optimized_throughput_str,
1428+
throughput_improvement=throughput_improvement_str,
13991429
)
14001430
new_explanation = Explanation(
14011431
raw_explanation_message=new_explanation_raw_str or explanation.raw_explanation_message,
@@ -1406,6 +1436,8 @@ def process_review(
14061436
function_name=explanation.function_name,
14071437
file_path=explanation.file_path,
14081438
benchmark_details=explanation.benchmark_details,
1439+
original_async_throughput=explanation.original_async_throughput,
1440+
best_async_throughput=explanation.best_async_throughput,
14091441
)
14101442
self.log_successful_optimization(new_explanation, generated_tests, exp_type)
14111443

@@ -1633,6 +1665,14 @@ def establish_original_code_baseline(
16331665
console.rule()
16341666
logger.debug(f"Total original code runtime (ns): {total_timing}")
16351667

1668+
async_throughput = None
1669+
if self.function_to_optimize.is_async:
1670+
async_throughput = calculate_function_throughput_from_test_results(
1671+
benchmarking_results, self.function_to_optimize.function_name
1672+
)
1673+
logger.debug(f"Original async function throughput: {async_throughput} calls/second")
1674+
console.rule()
1675+
16361676
if self.args.benchmark:
16371677
replay_benchmarking_test_results = benchmarking_results.group_by_benchmarks(
16381678
self.total_benchmark_timings.keys(), self.replay_tests_dir, self.project_root
@@ -1646,6 +1686,7 @@ def establish_original_code_baseline(
16461686
runtime=total_timing,
16471687
coverage_results=coverage_results,
16481688
line_profile_results=line_profile_results,
1689+
async_throughput=async_throughput,
16491690
),
16501691
functions_to_remove,
16511692
)
@@ -1792,6 +1833,14 @@ def run_optimized_candidate(
17921833
console.rule()
17931834

17941835
logger.debug(f"Total optimized code {optimization_candidate_index} runtime (ns): {total_candidate_timing}")
1836+
1837+
candidate_async_throughput = None
1838+
if self.function_to_optimize.is_async:
1839+
candidate_async_throughput = calculate_function_throughput_from_test_results(
1840+
candidate_benchmarking_results, self.function_to_optimize.function_name
1841+
)
1842+
logger.debug(f"Candidate async function throughput: {candidate_async_throughput} calls/second")
1843+
17951844
if self.args.benchmark:
17961845
candidate_replay_benchmarking_results = candidate_benchmarking_results.group_by_benchmarks(
17971846
self.total_benchmark_timings.keys(), self.replay_tests_dir, self.project_root
@@ -1811,6 +1860,7 @@ def run_optimized_candidate(
18111860
else None,
18121861
optimization_candidate_index=optimization_candidate_index,
18131862
total_candidate_timing=total_candidate_timing,
1863+
async_throughput=candidate_async_throughput,
18141864
)
18151865
)
18161866

@@ -1902,8 +1952,10 @@ def run_and_parse_tests(
19021952
coverage_database_file=coverage_database_file,
19031953
coverage_config_file=coverage_config_file,
19041954
)
1905-
else:
1906-
results, coverage_results = parse_line_profile_results(line_profiler_output_file=line_profiler_output_file)
1955+
if testing_type == TestingMode.PERFORMANCE:
1956+
results.perf_stdout = run_result.stdout
1957+
return results, coverage_results
1958+
results, coverage_results = parse_line_profile_results(line_profiler_output_file=line_profiler_output_file)
19071959
return results, coverage_results
19081960

19091961
def submit_test_generation_tasks(

0 commit comments

Comments
 (0)