Skip to content

Commit f715d32

Browse files
committed
refactor: reduce lru_cache maxsize for performance optimization across multiple modules
1 parent 6cbefe2 commit f715d32

File tree

11 files changed

+86
-173
lines changed

11 files changed

+86
-173
lines changed

packages/core/src/robotcode/core/text_document.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def position_from_utf16(lines: List[str], position: Position) -> Position:
4848
return Position(line=position.line, character=utf32_offset)
4949

5050

51-
@functools.lru_cache(maxsize=8192)
51+
@functools.lru_cache(maxsize=1024)
5252
def has_multibyte_char(line: str) -> bool:
5353
return any(is_multibyte_char(c) for c in line)
5454

packages/core/src/robotcode/core/utils/dataclasses.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
__to_snake_case_cache: Dict[str, str] = {}
4848

4949

50-
@functools.lru_cache(maxsize=None)
50+
@functools.lru_cache(maxsize=1024)
5151
def to_snake_case(s: str) -> str:
5252
result = __to_snake_case_cache.get(s, __not_valid)
5353
if result is __not_valid:
@@ -66,7 +66,7 @@ def to_snake_case(s: str) -> str:
6666
__to_snake_camel_cache: Dict[str, str] = {}
6767

6868

69-
@functools.lru_cache(maxsize=None)
69+
@functools.lru_cache(maxsize=1024)
7070
def to_camel_case(s: str) -> str:
7171
result = __to_snake_camel_cache.get(s, __not_valid)
7272
if result is __not_valid:

packages/core/src/robotcode/core/utils/glob_path.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def _glob_pattern_to_re(pattern: str) -> str:
6060
return result
6161

6262

63-
@functools.lru_cache(maxsize=8192)
63+
@functools.lru_cache(maxsize=1024)
6464
def _compile_glob_pattern(pattern: str) -> "re.Pattern[str]":
6565
return re.compile(_glob_pattern_to_re(pattern))
6666

packages/robot/src/robotcode/robot/diagnostics/entities.py

Lines changed: 25 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,13 @@
1-
import functools
21
from dataclasses import dataclass, field
32
from enum import Enum
43
from typing import (
54
TYPE_CHECKING,
65
Any,
7-
Callable,
8-
Generic,
96
List,
107
Optional,
118
Tuple,
12-
TypeVar,
13-
cast,
149
)
1510

16-
from typing_extensions import Concatenate, ParamSpec
17-
1811
from robot.parsing.lexer.tokens import Token
1912
from robotcode.core.lsp.types import Position, Range
2013

@@ -24,60 +17,8 @@
2417
if TYPE_CHECKING:
2518
from robotcode.robot.diagnostics.library_doc import KeywordDoc, LibraryDoc
2619

27-
_F = TypeVar("_F", bound=Callable[..., Any])
28-
29-
30-
_NOT_SET = object()
31-
32-
33-
def single_call(func: _F) -> _F:
34-
result = _NOT_SET
35-
36-
def wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
37-
nonlocal result
38-
39-
if result is _NOT_SET:
40-
result = func(self, *args, **kwargs)
41-
42-
return result
43-
44-
return cast(_F, wrapper)
45-
4620

47-
P = ParamSpec("P")
48-
R = TypeVar("R")
49-
50-
51-
class cached_method(Generic[P, R]): # noqa: N801
52-
def __init__(
53-
self, func: Optional[Callable[Concatenate[Any, P], R]] = None, *, maxsize: Optional[int] = None
54-
) -> None:
55-
self.func: Optional[Callable[Concatenate[Any, P], R]] = func
56-
self._maxsize = maxsize
57-
self.cache_name: Optional[str] = None
58-
if func is not None:
59-
functools.update_wrapper(self, func)
60-
61-
def __set_name__(self, owner: type, name: str) -> None:
62-
self.cache_name = f"__cached_{owner.__name__}_{name}"
63-
64-
def __call__(self, func: Callable[Concatenate[Any, P], R]) -> "cached_method[P, R]":
65-
self.func = func
66-
functools.update_wrapper(self, func)
67-
return self
68-
69-
def __get__(self, instance: Any, owner: Optional[type] = None) -> Callable[P, R]:
70-
cached = instance.__dict__.get(self.cache_name, _NOT_SET)
71-
if cached is _NOT_SET:
72-
assert self.func is not None
73-
74-
bound_method = self.func.__get__(instance, owner)
75-
cached = functools.lru_cache(maxsize=self._maxsize)(bound_method)
76-
instance.__dict__[self.cache_name] = cached
77-
return cast(Callable[P, R], cached)
78-
79-
80-
@dataclass
21+
@dataclass(slots=True)
8122
class SourceEntity:
8223
line_no: int
8324
col_offset: int
@@ -92,7 +33,6 @@ def range(self) -> Range:
9233
end=Position(line=self.end_line_no - 1, character=self.end_col_offset),
9334
)
9435

95-
@single_call
9636
def __hash__(self) -> int:
9737
return hash(
9838
(
@@ -105,7 +45,7 @@ def __hash__(self) -> int:
10545
)
10646

10747

108-
@dataclass
48+
@dataclass(slots=True)
10949
class Import(SourceEntity):
11050
name: Optional[str]
11151
name_token: Optional[Token]
@@ -124,7 +64,7 @@ def range(self) -> Range:
12464
)
12565

12666

127-
@dataclass
67+
@dataclass(slots=True)
12868
class LibraryImport(Import):
12969
args: Tuple[str, ...] = ()
13070
alias: Optional[str] = None
@@ -143,23 +83,20 @@ def alias_range(self) -> Range:
14383
),
14484
)
14585

146-
@single_call
14786
def __hash__(self) -> int:
14887
return hash((type(self), self.name, self.args, self.alias))
14988

15089

151-
@dataclass
90+
@dataclass(slots=True)
15291
class ResourceImport(Import):
153-
@single_call
15492
def __hash__(self) -> int:
15593
return hash((type(self), self.name))
15694

15795

158-
@dataclass
96+
@dataclass(slots=True)
15997
class VariablesImport(Import):
16098
args: Tuple[str, ...] = ()
16199

162-
@single_call
163100
def __hash__(self) -> int:
164101
return hash((type(self), self.name, self.args))
165102

@@ -178,7 +115,7 @@ class VariableDefinitionType(Enum):
178115
VARIABLE_NOT_FOUND = "variable not found"
179116

180117

181-
@dataclass
118+
@dataclass(slots=True)
182119
class VariableDefinition(SourceEntity):
183120
name: str
184121
name_token: Optional[Token] # TODO: this is not needed anymore, but kept for compatibility
@@ -192,17 +129,16 @@ class VariableDefinition(SourceEntity):
192129
value_is_native: bool = field(default=False, compare=False)
193130
value_type: Optional[str] = field(default=None, compare=False)
194131

195-
@functools.cached_property
132+
@property
196133
def matcher(self) -> VariableMatcher:
197134
return search_variable(self.name)
198135

199-
@functools.cached_property
136+
@property
200137
def convertable_name(self) -> str:
201138
m = self.matcher
202139
value_type = f": {self.value_type}" if self.value_type else ""
203140
return f"{m.identifier}{{{m.base.strip()}{value_type}}}"
204141

205-
@single_call
206142
def __hash__(self) -> int:
207143
return hash((self.type, self.name, self.source, self.range))
208144

@@ -221,82 +157,74 @@ def range(self) -> Range:
221157
)
222158

223159

224-
@dataclass
160+
@dataclass(slots=True)
225161
class TestVariableDefinition(VariableDefinition):
226162
type: VariableDefinitionType = VariableDefinitionType.TEST_VARIABLE
227163

228-
@single_call
229164
def __hash__(self) -> int:
230165
return hash((self.type, self.name, self.source, self.range))
231166

232167

233-
@dataclass
168+
@dataclass(slots=True)
234169
class LocalVariableDefinition(VariableDefinition):
235170
type: VariableDefinitionType = VariableDefinitionType.LOCAL_VARIABLE
236171

237-
@single_call
238172
def __hash__(self) -> int:
239173
return hash((self.type, self.name, self.source, self.range))
240174

241175

242-
@dataclass
176+
@dataclass(slots=True)
243177
class GlobalVariableDefinition(VariableDefinition):
244178
type: VariableDefinitionType = VariableDefinitionType.GLOBAL_VARIABLE
245179

246-
@single_call
247180
def __hash__(self) -> int:
248181
return hash((self.type, self.name, self.source, self.range))
249182

250183

251-
@dataclass
184+
@dataclass(slots=True)
252185
class BuiltInVariableDefinition(GlobalVariableDefinition):
253186
type: VariableDefinitionType = VariableDefinitionType.BUILTIN_VARIABLE
254187
resolvable: bool = True
255188

256-
@single_call
257189
def __hash__(self) -> int:
258190
return hash((self.type, self.name, self.source, self.range))
259191

260192

261-
@dataclass
193+
@dataclass(slots=True)
262194
class CommandLineVariableDefinition(GlobalVariableDefinition):
263195
type: VariableDefinitionType = VariableDefinitionType.COMMAND_LINE_VARIABLE
264196
resolvable: bool = True
265197

266-
@single_call
267198
def __hash__(self) -> int:
268199
return hash((self.type, self.name, self.source, self.range))
269200

270201

271-
@dataclass
202+
@dataclass(slots=True)
272203
class ArgumentDefinition(LocalVariableDefinition):
273204
type: VariableDefinitionType = VariableDefinitionType.ARGUMENT
274205
keyword_doc: Optional["KeywordDoc"] = field(default=None, compare=False, metadata={"nosave": True})
275206

276-
@single_call
277207
def __hash__(self) -> int:
278208
return hash((self.type, self.name, self.source, self.range))
279209

280210

281-
@dataclass
211+
@dataclass(slots=True)
282212
class EmbeddedArgumentDefinition(ArgumentDefinition):
283213
pattern: Optional[str] = field(default=None, compare=False)
284214

285-
@single_call
286215
def __hash__(self) -> int:
287216
return hash((self.type, self.name, self.source, self.range))
288217

289218

290-
@dataclass
219+
@dataclass(slots=True)
291220
class LibraryArgumentDefinition(ArgumentDefinition):
292221
type: VariableDefinitionType = VariableDefinitionType.LIBRARY_ARGUMENT
293222

294-
@single_call
295223
def __hash__(self) -> int:
296224
return hash((self.type, self.name, self.source, self.range))
297225

298226

299-
@dataclass(frozen=True, eq=False, repr=False)
227+
@dataclass(slots=True, frozen=True, eq=False, repr=False)
300228
class NativeValue:
301229
value: Any
302230

@@ -307,39 +235,36 @@ def __str__(self) -> str:
307235
return str(self.value)
308236

309237

310-
@dataclass
238+
@dataclass(slots=True)
311239
class ImportedVariableDefinition(VariableDefinition):
312240
type: VariableDefinitionType = VariableDefinitionType.IMPORTED_VARIABLE
313241
value: Optional[NativeValue] = field(default=None, compare=False)
314242

315-
@single_call
316243
def __hash__(self) -> int:
317244
return hash((self.type, self.name, self.source, self.range))
318245

319246

320-
@dataclass
247+
@dataclass(slots=True)
321248
class EnvironmentVariableDefinition(VariableDefinition):
322249
type: VariableDefinitionType = VariableDefinitionType.ENVIRONMENT_VARIABLE
323250
resolvable: bool = True
324251

325252
default_value: Any = field(default=None, compare=False)
326253

327-
@single_call
328254
def __hash__(self) -> int:
329255
return hash((self.type, self.name, self.source, self.range))
330256

331257

332-
@dataclass
258+
@dataclass(slots=True)
333259
class VariableNotFoundDefinition(VariableDefinition):
334260
type: VariableDefinitionType = VariableDefinitionType.VARIABLE_NOT_FOUND
335261
resolvable: bool = False
336262

337-
@single_call
338263
def __hash__(self) -> int:
339264
return hash((self.type, self.name, self.source, self.range))
340265

341266

342-
@dataclass
267+
@dataclass(slots=True)
343268
class LibraryEntry:
344269
name: str
345270
import_name: str
@@ -358,7 +283,6 @@ def __str__(self) -> str:
358283
result += f" WITH NAME {self.alias}"
359284
return result
360285

361-
@single_call
362286
def __hash__(self) -> int:
363287
return hash(
364288
(
@@ -374,12 +298,11 @@ def __hash__(self) -> int:
374298
)
375299

376300

377-
@dataclass
301+
@dataclass(slots=True)
378302
class ResourceEntry(LibraryEntry):
379303
imports: List[Import] = field(default_factory=list, compare=False)
380304
variables: List[VariableDefinition] = field(default_factory=list, compare=False)
381305

382-
@single_call
383306
def __hash__(self) -> int:
384307
return hash(
385308
(
@@ -392,11 +315,10 @@ def __hash__(self) -> int:
392315
)
393316

394317

395-
@dataclass
318+
@dataclass(slots=True)
396319
class VariablesEntry(LibraryEntry):
397320
variables: List[ImportedVariableDefinition] = field(default_factory=list, compare=False)
398321

399-
@single_call
400322
def __hash__(self) -> int:
401323
return hash(
402324
(
@@ -410,11 +332,10 @@ def __hash__(self) -> int:
410332
)
411333

412334

413-
@dataclass
335+
@dataclass(slots=True)
414336
class TestCaseDefinition(SourceEntity):
415337
name: str
416338

417-
@single_call
418339
def __hash__(self) -> int:
419340
return hash(
420341
(
@@ -428,11 +349,10 @@ def __hash__(self) -> int:
428349
)
429350

430351

431-
@dataclass
352+
@dataclass(slots=True)
432353
class TagDefinition(SourceEntity):
433354
name: str
434355

435-
@single_call
436356
def __hash__(self) -> int:
437357
return hash(
438358
(

0 commit comments

Comments
 (0)