Skip to content

Commit a82948b

Browse files
authored
Micro-optimize chained plugin (#19464)
Avoid using lambdas in the most expensive hooks, since they are slower than direct method calls. Also use `if hook is None` checks instead of `if hook`, since the prior is more efficient when compiled. I used trace logging to look for generic/unoptimized function calls, and it was clear that ChainedPlugin was doing many unoptimized calls that were easy to avoid. This duplicates some code, but I think it's fine since this code is updated very rarely but the code paths are very hot. This is a part of a set of micro-optimizations that improve self check performance by ~5.5%.
1 parent 5f5871d commit a82948b

File tree

1 file changed

+31
-6
lines changed

1 file changed

+31
-6
lines changed

mypy/plugin.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -846,26 +846,51 @@ def get_additional_deps(self, file: MypyFile) -> list[tuple[int, str, int]]:
846846
return deps
847847

848848
def get_type_analyze_hook(self, fullname: str) -> Callable[[AnalyzeTypeContext], Type] | None:
849-
return self._find_hook(lambda plugin: plugin.get_type_analyze_hook(fullname))
849+
# Micro-optimization: Inline iteration over plugins
850+
for plugin in self._plugins:
851+
hook = plugin.get_type_analyze_hook(fullname)
852+
if hook is not None:
853+
return hook
854+
return None
850855

851856
def get_function_signature_hook(
852857
self, fullname: str
853858
) -> Callable[[FunctionSigContext], FunctionLike] | None:
854-
return self._find_hook(lambda plugin: plugin.get_function_signature_hook(fullname))
859+
# Micro-optimization: Inline iteration over plugins
860+
for plugin in self._plugins:
861+
hook = plugin.get_function_signature_hook(fullname)
862+
if hook is not None:
863+
return hook
864+
return None
855865

856866
def get_function_hook(self, fullname: str) -> Callable[[FunctionContext], Type] | None:
857867
return self._find_hook(lambda plugin: plugin.get_function_hook(fullname))
858868

859869
def get_method_signature_hook(
860870
self, fullname: str
861871
) -> Callable[[MethodSigContext], FunctionLike] | None:
862-
return self._find_hook(lambda plugin: plugin.get_method_signature_hook(fullname))
872+
# Micro-optimization: Inline iteration over plugins
873+
for plugin in self._plugins:
874+
hook = plugin.get_method_signature_hook(fullname)
875+
if hook is not None:
876+
return hook
877+
return None
863878

864879
def get_method_hook(self, fullname: str) -> Callable[[MethodContext], Type] | None:
865-
return self._find_hook(lambda plugin: plugin.get_method_hook(fullname))
880+
# Micro-optimization: Inline iteration over plugins
881+
for plugin in self._plugins:
882+
hook = plugin.get_method_hook(fullname)
883+
if hook is not None:
884+
return hook
885+
return None
866886

867887
def get_attribute_hook(self, fullname: str) -> Callable[[AttributeContext], Type] | None:
868-
return self._find_hook(lambda plugin: plugin.get_attribute_hook(fullname))
888+
# Micro-optimization: Inline iteration over plugins
889+
for plugin in self._plugins:
890+
hook = plugin.get_attribute_hook(fullname)
891+
if hook is not None:
892+
return hook
893+
return None
869894

870895
def get_class_attribute_hook(self, fullname: str) -> Callable[[AttributeContext], Type] | None:
871896
return self._find_hook(lambda plugin: plugin.get_class_attribute_hook(fullname))
@@ -897,6 +922,6 @@ def get_dynamic_class_hook(
897922
def _find_hook(self, lookup: Callable[[Plugin], T]) -> T | None:
898923
for plugin in self._plugins:
899924
hook = lookup(plugin)
900-
if hook:
925+
if hook is not None:
901926
return hook
902927
return None

0 commit comments

Comments
 (0)