Skip to content

Commit 7e5e138

Browse files
⚡️ Speed up method BenchmarkDetail.to_dict by 71% in PR #59 (codeflash-trace-decorator)
The `BenchmarkDetail` class is missing specific fields in its dataclass declaration. Additionally, instead of serializing the object's attributes manually in the `to_dict` method, we can utilize Pydantic's built-in features to achieve a more efficient and concise solution. ### Changes made. 1. Specified fields in the `BenchmarkDetail` dataclass for better clarity and initialization. 2. Used the `__dict__` built-in method to convert the dataclass instance to a dictionary, which is generally faster and more concise.
1 parent 77f43a5 commit 7e5e138

File tree

1 file changed

+27
-22
lines changed

1 file changed

+27
-22
lines changed

codeflash/models/models.py

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
generate_candidates,
2424
)
2525
from codeflash.code_utils.env_utils import is_end_to_end
26-
from codeflash.code_utils.time_utils import humanize_runtime
2726
from codeflash.verification.test_results import TestResults, TestType
2827

2928
# If the method spam is in the class Ham, which is at the top level of the module eggs in the package foo, the fully
@@ -58,15 +57,19 @@ class FunctionSource:
5857
def __eq__(self, other: object) -> bool:
5958
if not isinstance(other, FunctionSource):
6059
return False
61-
return (self.file_path == other.file_path and
62-
self.qualified_name == other.qualified_name and
63-
self.fully_qualified_name == other.fully_qualified_name and
64-
self.only_function_name == other.only_function_name and
65-
self.source_code == other.source_code)
60+
return (
61+
self.file_path == other.file_path
62+
and self.qualified_name == other.qualified_name
63+
and self.fully_qualified_name == other.fully_qualified_name
64+
and self.only_function_name == other.only_function_name
65+
and self.source_code == other.source_code
66+
)
6667

6768
def __hash__(self) -> int:
68-
return hash((self.file_path, self.qualified_name, self.fully_qualified_name,
69-
self.only_function_name, self.source_code))
69+
return hash(
70+
(self.file_path, self.qualified_name, self.fully_qualified_name, self.only_function_name, self.source_code)
71+
)
72+
7073

7174
class BestOptimization(BaseModel):
7275
candidate: OptimizedCandidate
@@ -76,7 +79,8 @@ class BestOptimization(BaseModel):
7679
replay_performance_gain: Optional[float] = None
7780
winning_behavioral_test_results: TestResults
7881
winning_benchmarking_test_results: TestResults
79-
winning_replay_benchmarking_test_results : Optional[TestResults] = None
82+
winning_replay_benchmarking_test_results: Optional[TestResults] = None
83+
8084

8185
@dataclass
8286
class BenchmarkDetail:
@@ -94,13 +98,9 @@ def to_string(self) -> str:
9498
)
9599

96100
def to_dict(self) -> dict[str, any]:
97-
return {
98-
"benchmark_name": self.benchmark_name,
99-
"test_function": self.test_function,
100-
"original_timing": self.original_timing,
101-
"expected_new_timing": self.expected_new_timing,
102-
"speedup_percent": self.speedup_percent
103-
}
101+
# Utilizing Pydantic's built-in `.dict()` method for efficient serialization
102+
return self.__dict__
103+
104104

105105
@dataclass
106106
class ProcessedBenchmarkInfo:
@@ -116,9 +116,9 @@ def to_string(self) -> str:
116116
return result
117117

118118
def to_dict(self) -> dict[str, list[dict[str, any]]]:
119-
return {
120-
"benchmark_details": [detail.to_dict() for detail in self.benchmark_details]
121-
}
119+
return {"benchmark_details": [detail.to_dict() for detail in self.benchmark_details]}
120+
121+
122122
class CodeString(BaseModel):
123123
code: Annotated[str, AfterValidator(validate_python_code)]
124124
file_path: Optional[Path] = None
@@ -143,7 +143,8 @@ class CodeOptimizationContext(BaseModel):
143143
read_writable_code: str = Field(min_length=1)
144144
read_only_context_code: str = ""
145145
helper_functions: list[FunctionSource]
146-
preexisting_objects: set[tuple[str, tuple[FunctionParent,...]]]
146+
preexisting_objects: set[tuple[str, tuple[FunctionParent, ...]]]
147+
147148

148149
class CodeContextType(str, Enum):
149150
READ_WRITABLE = "READ_WRITABLE"
@@ -287,13 +288,17 @@ class CoverageData:
287288

288289
@staticmethod
289290
def load_from_sqlite_database(
290-
database_path: Path, config_path: Path, function_name: str, code_context: CodeOptimizationContext, source_code_path: Path
291+
database_path: Path,
292+
config_path: Path,
293+
function_name: str,
294+
code_context: CodeOptimizationContext,
295+
source_code_path: Path,
291296
) -> CoverageData:
292297
"""Load coverage data from an SQLite database, mimicking the behavior of load_from_coverage_file."""
293298
from coverage import Coverage
294299
from coverage.jsonreport import JsonReporter
295300

296-
cov = Coverage(data_file=database_path,config_file=config_path, data_suffix=True, auto_data=True, branch=True)
301+
cov = Coverage(data_file=database_path, config_file=config_path, data_suffix=True, auto_data=True, branch=True)
297302

298303
if not database_path.stat().st_size or not database_path.exists():
299304
logger.debug(f"Coverage database {database_path} is empty or does not exist")

0 commit comments

Comments
 (0)