Skip to content

Commit 078b5c0

Browse files
Saga4saga4mohammedahmed18
authored
LSP reduce no of candidates (#729)
* LSP reduce no of candidates * config revert * pass reference values to aiservices * line profiling loading msg --------- Co-authored-by: saga4 <saga4@codeflashs-MacBook-Air.local> Co-authored-by: ali <mohammed18200118@gmail.com>
1 parent e84e57a commit 078b5c0

File tree

5 files changed

+71
-27
lines changed

5 files changed

+71
-27
lines changed

codeflash/api/aiservice.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from pydantic.json import pydantic_encoder
1111

1212
from codeflash.cli_cmds.console import console, logger
13+
from codeflash.code_utils.config_consts import get_n_candidates, get_n_candidates_lp
1314
from codeflash.code_utils.env_utils import get_codeflash_api_key
1415
from codeflash.code_utils.git_utils import get_last_commit_author_if_pr_exists, get_repo_owner_and_name
1516
from codeflash.lsp.helpers import is_LSP_enabled
@@ -131,6 +132,7 @@ def optimize_python_code( # noqa: D417
131132
"current_username": get_last_commit_author_if_pr_exists(None),
132133
"repo_owner": git_repo_owner,
133134
"repo_name": git_repo_name,
135+
"n_candidates": get_n_candidates(),
134136
}
135137

136138
logger.info("!lsp|Generating optimized candidates…")
@@ -192,6 +194,7 @@ def optimize_python_code_line_profiler( # noqa: D417
192194
"experiment_metadata": experiment_metadata,
193195
"codeflash_version": codeflash_version,
194196
"lsp_mode": is_LSP_enabled(),
197+
"n_candidates_lp": get_n_candidates_lp(),
195198
}
196199

197200
console.rule()

codeflash/code_utils/config_consts.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,34 @@
1111
MIN_TESTCASE_PASSED_THRESHOLD = 6
1212
REPEAT_OPTIMIZATION_PROBABILITY = 0.1
1313
DEFAULT_IMPORTANCE_THRESHOLD = 0.001
14+
N_CANDIDATES_LP = 6
15+
16+
# LSP-specific
17+
N_CANDIDATES_LSP = 3
18+
N_TESTS_TO_GENERATE_LSP = 2
19+
TOTAL_LOOPING_TIME_LSP = 10.0 # Kept same timing for LSP mode to avoid in increase in performance reporting
20+
N_CANDIDATES_LP_LSP = 3
21+
22+
23+
def get_n_candidates() -> int:
24+
from codeflash.lsp.helpers import is_LSP_enabled
25+
26+
return N_CANDIDATES_LSP if is_LSP_enabled() else N_CANDIDATES
27+
28+
29+
def get_n_candidates_lp() -> int:
30+
from codeflash.lsp.helpers import is_LSP_enabled
31+
32+
return N_CANDIDATES_LP_LSP if is_LSP_enabled() else N_CANDIDATES_LP
33+
34+
35+
def get_n_tests_to_generate() -> int:
36+
from codeflash.lsp.helpers import is_LSP_enabled
37+
38+
return N_TESTS_TO_GENERATE_LSP if is_LSP_enabled() else N_TESTS_TO_GENERATE
39+
40+
41+
def get_total_looping_time() -> float:
42+
from codeflash.lsp.helpers import is_LSP_enabled
43+
44+
return TOTAL_LOOPING_TIME_LSP if is_LSP_enabled() else TOTAL_LOOPING_TIME

codeflash/code_utils/git_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from unidiff import PatchSet
1717

1818
from codeflash.cli_cmds.console import logger
19-
from codeflash.code_utils.config_consts import N_CANDIDATES
19+
from codeflash.code_utils.config_consts import get_n_candidates
2020

2121
if TYPE_CHECKING:
2222
from git import Repo
@@ -164,7 +164,7 @@ def create_git_worktrees(
164164
) -> tuple[Path | None, list[Path]]:
165165
if git_root and worktree_root_dir:
166166
worktree_root = Path(tempfile.mkdtemp(dir=worktree_root_dir))
167-
worktrees = [Path(tempfile.mkdtemp(dir=worktree_root)) for _ in range(N_CANDIDATES + 1)]
167+
worktrees = [Path(tempfile.mkdtemp(dir=worktree_root)) for _ in range(get_n_candidates() + 1)]
168168
for worktree in worktrees:
169169
subprocess.run(["git", "worktree", "add", "-d", worktree], cwd=module_root, check=True)
170170
else:

codeflash/optimization/function_optimizer.py

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,11 @@
4444
from codeflash.code_utils.config_consts import (
4545
COVERAGE_THRESHOLD,
4646
INDIVIDUAL_TESTCASE_TIMEOUT,
47-
N_CANDIDATES,
48-
N_TESTS_TO_GENERATE,
4947
REPEAT_OPTIMIZATION_PROBABILITY,
50-
TOTAL_LOOPING_TIME,
48+
get_n_candidates,
49+
get_n_candidates_lp,
50+
get_n_tests_to_generate,
51+
get_total_looping_time,
5152
)
5253
from codeflash.code_utils.deduplicate_code import normalize_code
5354
from codeflash.code_utils.edit_generated_tests import (
@@ -236,8 +237,9 @@ def __init__(
236237
self.generate_and_instrument_tests_results: (
237238
tuple[GeneratedTestsList, dict[str, set[FunctionCalledInTest]], OptimizationSet] | None
238239
) = None
240+
n_tests = get_n_tests_to_generate()
239241
self.executor = concurrent.futures.ThreadPoolExecutor(
240-
max_workers=N_TESTS_TO_GENERATE + 2 if self.experiment_id is None else N_TESTS_TO_GENERATE + 3
242+
max_workers=n_tests + 2 if self.experiment_id is None else n_tests + 3
241243
)
242244

243245
def can_be_optimized(self) -> Result[tuple[bool, CodeOptimizationContext, dict[Path, str]], str]:
@@ -287,17 +289,18 @@ def generate_and_instrument_tests(
287289
]
288290
]:
289291
"""Generate and instrument tests, returning all necessary data for optimization."""
292+
n_tests = get_n_tests_to_generate()
290293
generated_test_paths = [
291294
get_test_file_path(
292295
self.test_cfg.tests_root, self.function_to_optimize.function_name, test_index, test_type="unit"
293296
)
294-
for test_index in range(N_TESTS_TO_GENERATE)
297+
for test_index in range(n_tests)
295298
]
296299
generated_perf_test_paths = [
297300
get_test_file_path(
298301
self.test_cfg.tests_root, self.function_to_optimize.function_name, test_index, test_type="perf"
299302
)
300-
for test_index in range(N_TESTS_TO_GENERATE)
303+
for test_index in range(n_tests)
301304
]
302305

303306
with progress_bar(
@@ -484,7 +487,7 @@ def determine_best_candidate(
484487
dependency_code=code_context.read_only_context_code,
485488
trace_id=self.function_trace_id[:-4] + exp_type if self.experiment_id else self.function_trace_id,
486489
line_profiler_results=original_code_baseline.line_profile_results["str_out"],
487-
num_candidates=10,
490+
num_candidates=get_n_candidates_lp(),
488491
experiment_metadata=ExperimentMetadata(
489492
id=self.experiment_id, group="control" if exp_type == "EXP0" else "experiment"
490493
)
@@ -1058,7 +1061,8 @@ def generate_tests_and_optimizations(
10581061
generated_perf_test_paths: list[Path],
10591062
run_experiment: bool = False, # noqa: FBT001, FBT002
10601063
) -> Result[tuple[GeneratedTestsList, dict[str, set[FunctionCalledInTest]], OptimizationSet], str]:
1061-
assert len(generated_test_paths) == N_TESTS_TO_GENERATE
1064+
n_tests = get_n_tests_to_generate()
1065+
assert len(generated_test_paths) == n_tests
10621066
console.rule()
10631067
# Submit the test generation task as future
10641068
future_tests = self.submit_test_generation_tasks(
@@ -1068,12 +1072,13 @@ def generate_tests_and_optimizations(
10681072
generated_test_paths,
10691073
generated_perf_test_paths,
10701074
)
1075+
n_candidates = get_n_candidates()
10711076
future_optimization_candidates = self.executor.submit(
10721077
self.aiservice_client.optimize_python_code,
10731078
read_writable_code.markdown,
10741079
read_only_context_code,
10751080
self.function_trace_id[:-4] + "EXP0" if run_experiment else self.function_trace_id,
1076-
N_CANDIDATES,
1081+
n_candidates,
10771082
ExperimentMetadata(id=self.experiment_id, group="control") if run_experiment else None,
10781083
)
10791084
future_candidates_exp = None
@@ -1088,7 +1093,7 @@ def generate_tests_and_optimizations(
10881093
read_writable_code.markdown,
10891094
read_only_context_code,
10901095
self.function_trace_id[:-4] + "EXP1",
1091-
N_CANDIDATES,
1096+
n_candidates,
10921097
ExperimentMetadata(id=self.experiment_id, group="experiment"),
10931098
)
10941099
futures.append(future_candidates_exp)
@@ -1477,12 +1482,13 @@ def establish_original_code_baseline(
14771482
instrument_codeflash_capture(
14781483
self.function_to_optimize, file_path_to_helper_classes, self.test_cfg.tests_root
14791484
)
1485+
total_looping_time = get_total_looping_time()
14801486
behavioral_results, coverage_results = self.run_and_parse_tests(
14811487
testing_type=TestingMode.BEHAVIOR,
14821488
test_env=test_env,
14831489
test_files=self.test_files,
14841490
optimization_iteration=0,
1485-
testing_time=TOTAL_LOOPING_TIME,
1491+
testing_time=total_looping_time,
14861492
enable_coverage=test_framework == "pytest",
14871493
code_context=code_context,
14881494
)
@@ -1503,7 +1509,7 @@ def establish_original_code_baseline(
15031509
)
15041510

15051511
if test_framework == "pytest":
1506-
with progress_bar("Performing detailed line profiling..."):
1512+
with progress_bar("Running line profiling to identify performance bottlenecks..."):
15071513
line_profile_results = self.line_profiler_step(
15081514
code_context=code_context, original_helper_code=original_helper_code, candidate_index=0
15091515
)
@@ -1514,15 +1520,15 @@ def establish_original_code_baseline(
15141520
test_env=test_env,
15151521
test_files=self.test_files,
15161522
optimization_iteration=0,
1517-
testing_time=TOTAL_LOOPING_TIME,
1523+
testing_time=total_looping_time,
15181524
enable_coverage=False,
15191525
code_context=code_context,
15201526
)
15211527
else:
15221528
benchmarking_results = TestResults()
15231529
start_time: float = time.time()
15241530
for i in range(100):
1525-
if i >= 5 and time.time() - start_time >= TOTAL_LOOPING_TIME * 1.5:
1531+
if i >= 5 and time.time() - start_time >= total_looping_time * 1.5:
15261532
# * 1.5 to give unittest a bit more time to run
15271533
break
15281534
test_env["CODEFLASH_LOOP_INDEX"] = str(i + 1)
@@ -1532,7 +1538,7 @@ def establish_original_code_baseline(
15321538
test_env=test_env,
15331539
test_files=self.test_files,
15341540
optimization_iteration=0,
1535-
testing_time=TOTAL_LOOPING_TIME,
1541+
testing_time=total_looping_time,
15361542
enable_coverage=False,
15371543
code_context=code_context,
15381544
unittest_loop_index=i + 1,
@@ -1617,12 +1623,13 @@ def run_optimized_candidate(
16171623
self.function_to_optimize, file_path_to_helper_classes, self.test_cfg.tests_root
16181624
)
16191625

1626+
total_looping_time = get_total_looping_time()
16201627
candidate_behavior_results, _ = self.run_and_parse_tests(
16211628
testing_type=TestingMode.BEHAVIOR,
16221629
test_env=test_env,
16231630
test_files=self.test_files,
16241631
optimization_iteration=optimization_candidate_index,
1625-
testing_time=TOTAL_LOOPING_TIME,
1632+
testing_time=total_looping_time,
16261633
enable_coverage=False,
16271634
)
16281635
# Remove instrumentation
@@ -1653,7 +1660,7 @@ def run_optimized_candidate(
16531660
test_env=test_env,
16541661
test_files=self.test_files,
16551662
optimization_iteration=optimization_candidate_index,
1656-
testing_time=TOTAL_LOOPING_TIME,
1663+
testing_time=total_looping_time,
16571664
enable_coverage=False,
16581665
)
16591666
loop_count = (
@@ -1671,7 +1678,7 @@ def run_optimized_candidate(
16711678
start_time: float = time.time()
16721679
loop_count = 0
16731680
for i in range(100):
1674-
if i >= 5 and time.time() - start_time >= TOTAL_LOOPING_TIME * 1.5:
1681+
if i >= 5 and time.time() - start_time >= get_total_looping_time() * 1.5:
16751682
# * 1.5 to give unittest a bit more time to run
16761683
break
16771684
test_env["CODEFLASH_LOOP_INDEX"] = str(i + 1)
@@ -1680,7 +1687,7 @@ def run_optimized_candidate(
16801687
test_env=test_env,
16811688
test_files=self.test_files,
16821689
optimization_iteration=optimization_candidate_index,
1683-
testing_time=TOTAL_LOOPING_TIME,
1690+
testing_time=get_total_looping_time(),
16841691
unittest_loop_index=i + 1,
16851692
)
16861693
loop_count = i + 1
@@ -1719,7 +1726,7 @@ def run_and_parse_tests(
17191726
test_env: dict[str, str],
17201727
test_files: TestFiles,
17211728
optimization_iteration: int,
1722-
testing_time: float = TOTAL_LOOPING_TIME,
1729+
testing_time: float = get_total_looping_time(),
17231730
*,
17241731
enable_coverage: bool = False,
17251732
pytest_min_loops: int = 5,
@@ -1858,6 +1865,9 @@ def line_profiler_step(
18581865
self, code_context: CodeOptimizationContext, original_helper_code: dict[Path, str], candidate_index: int
18591866
) -> dict:
18601867
try:
1868+
logger.info("Running line profiling to identify performance bottlenecks…")
1869+
console.rule()
1870+
18611871
test_env = self.get_test_env(
18621872
codeflash_loop_index=0, codeflash_test_iteration=candidate_index, codeflash_tracer_disable=1
18631873
)
@@ -1867,7 +1877,7 @@ def line_profiler_step(
18671877
test_env=test_env,
18681878
test_files=self.test_files,
18691879
optimization_iteration=0,
1870-
testing_time=TOTAL_LOOPING_TIME,
1880+
testing_time=get_total_looping_time(),
18711881
enable_coverage=False,
18721882
code_context=code_context,
18731883
line_profiler_output_file=line_profiler_output_file,

codeflash/verification/test_runner.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from codeflash.cli_cmds.console import logger
99
from codeflash.code_utils.code_utils import custom_addopts, get_run_tmp_file
1010
from codeflash.code_utils.compat import IS_POSIX, SAFE_SYS_EXECUTABLE
11-
from codeflash.code_utils.config_consts import TOTAL_LOOPING_TIME
11+
from codeflash.code_utils.config_consts import get_total_looping_time
1212
from codeflash.code_utils.coverage_utils import prepare_coverage_files
1313
from codeflash.models.models import TestFiles, TestType
1414

@@ -37,7 +37,7 @@ def run_behavioral_tests(
3737
pytest_timeout: int | None = None,
3838
pytest_cmd: str = "pytest",
3939
verbose: bool = False,
40-
pytest_target_runtime_seconds: int = TOTAL_LOOPING_TIME,
40+
pytest_target_runtime_seconds: int = get_total_looping_time(),
4141
enable_coverage: bool = False,
4242
) -> tuple[Path, subprocess.CompletedProcess, Path | None, Path | None]:
4343
if test_framework == "pytest":
@@ -151,7 +151,7 @@ def run_line_profile_tests(
151151
cwd: Path,
152152
test_framework: str,
153153
*,
154-
pytest_target_runtime_seconds: float = TOTAL_LOOPING_TIME,
154+
pytest_target_runtime_seconds: float = get_total_looping_time(),
155155
verbose: bool = False,
156156
pytest_timeout: int | None = None,
157157
pytest_min_loops: int = 5, # noqa: ARG001
@@ -237,7 +237,7 @@ def run_benchmarking_tests(
237237
cwd: Path,
238238
test_framework: str,
239239
*,
240-
pytest_target_runtime_seconds: float = TOTAL_LOOPING_TIME,
240+
pytest_target_runtime_seconds: float = get_total_looping_time(),
241241
verbose: bool = False,
242242
pytest_timeout: int | None = None,
243243
pytest_min_loops: int = 5,

0 commit comments

Comments
 (0)