1111
1212from codeflash .code_utils .time_utils import humanize_runtime
1313from codeflash .models .models import BenchmarkDetail , TestResults
14+ from codeflash .result .critic import performance_gain , throughput_gain
1415
1516
1617@dataclass (frozen = True , config = {"arbitrary_types_allowed" : True })
@@ -23,9 +24,29 @@ class Explanation:
2324 function_name : str
2425 file_path : Path
2526 benchmark_details : Optional [list [BenchmarkDetail ]] = None
27+ original_async_throughput : Optional [int ] = None
28+ best_async_throughput : Optional [int ] = None
2629
2730 @property
2831 def perf_improvement_line (self ) -> str :
32+ runtime_improvement = self .speedup
33+
34+ if (
35+ self .original_async_throughput is not None
36+ and self .best_async_throughput is not None
37+ and self .original_async_throughput > 0
38+ ):
39+ throughput_improvement = throughput_gain (
40+ original_throughput = self .original_async_throughput ,
41+ optimized_throughput = self .best_async_throughput ,
42+ )
43+
44+ # Use throughput metrics if throughput improvement is better or runtime got worse
45+ if throughput_improvement > runtime_improvement or runtime_improvement <= 0 :
46+ throughput_pct = f"{ throughput_improvement * 100 :,.0f} %"
47+ throughput_x = f"{ throughput_improvement + 1 :,.2f} x"
48+ return f"{ throughput_pct } improvement ({ throughput_x } faster)."
49+
2950 return f"{ self .speedup_pct } improvement ({ self .speedup_x } faster)."
3051
3152 @property
@@ -45,6 +66,24 @@ def to_console_string(self) -> str:
4566 # TODO: Sometimes the explanation says something similar to "This is the code that was optimized", remove such parts
4667 original_runtime_human = humanize_runtime (self .original_runtime_ns )
4768 best_runtime_human = humanize_runtime (self .best_runtime_ns )
69+
70+ # Determine if we're showing throughput or runtime improvements
71+ runtime_improvement = self .speedup
72+ is_using_throughput_metric = False
73+
74+ if (
75+ self .original_async_throughput is not None
76+ and self .best_async_throughput is not None
77+ and self .original_async_throughput > 0
78+ ):
79+ throughput_improvement = throughput_gain (
80+ original_throughput = self .original_async_throughput ,
81+ optimized_throughput = self .best_async_throughput ,
82+ )
83+
84+ if throughput_improvement > runtime_improvement or runtime_improvement <= 0 :
85+ is_using_throughput_metric = True
86+
4887 benchmark_info = ""
4988
5089 if self .benchmark_details :
@@ -85,10 +124,18 @@ def to_console_string(self) -> str:
85124 console .print (table )
86125 benchmark_info = cast ("StringIO" , console .file ).getvalue () + "\n " # Cast for mypy
87126
127+ if is_using_throughput_metric :
128+ performance_description = (
129+ f"Throughput improved from { self .original_async_throughput } to { self .best_async_throughput } operations/second "
130+ f"(runtime: { original_runtime_human } → { best_runtime_human } )\n \n "
131+ )
132+ else :
133+ performance_description = f"Runtime went down from { original_runtime_human } to { best_runtime_human } \n \n "
134+
88135 return (
89136 f"Optimized { self .function_name } in { self .file_path } \n "
90137 f"{ self .perf_improvement_line } \n "
91- f"Runtime went down from { original_runtime_human } to { best_runtime_human } \n \n "
138+ + performance_description
92139 + (benchmark_info if benchmark_info else "" )
93140 + self .raw_explanation_message
94141 + " \n \n "
0 commit comments