8484 TestType ,
8585)
8686from 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+ )
8894from codeflash .result .explanation import Explanation
8995from codeflash .telemetry .posthog_cf import ph
9096from codeflash .verification .concolic_testing import generate_concolic_tests
9197from codeflash .verification .equivalence import compare_test_results
9298from codeflash .verification .instrument_codeflash_capture import instrument_codeflash_capture
9399from 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
95101from codeflash .verification .test_runner import run_behavioral_tests , run_benchmarking_tests , run_line_profile_tests
96102from codeflash .verification .verification_utils import get_test_file_path
97103from 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