aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/compilers/compilers.py
diff options
context:
space:
mode:
authorMarcel Hollerbach <mail@marcel-hollerbach.de>2020-01-17 19:16:57 +0100
committerJussi Pakkanen <jpakkane@gmail.com>2020-03-01 19:27:49 +0200
commit4524088d386d2e2315d8fef6ffedc11d8e9a394a (patch)
tree60ba6c5be3099694136908bebb2a7f2c0112a4b9 /mesonbuild/compilers/compilers.py
parent25cbcb19a9208ebf8f5cde3f8ecb91df0a2dfebf (diff)
downloadmeson-4524088d386d2e2315d8fef6ffedc11d8e9a394a.zip
meson-4524088d386d2e2315d8fef6ffedc11d8e9a394a.tar.gz
meson-4524088d386d2e2315d8fef6ffedc11d8e9a394a.tar.bz2
CompilerArgs: make lookup faster
in order to deduplicate arguments as much as possible, we need to check if a argument is already part of the list. Which is quite slow because we are checking 3 lists for that. In smaller projects this might be not of interested. However, in efl things are quite "heavy", alone generating the ninja file took 40 sec.. 16 sec. are spent in __iadd__ of CompilerArgs. What this patch does to speed this all up is: 1. We only check if a element is in post when we know that it must be in post same for pre. 2. the checks for if we already do contain a specific value are now done via a dict, and not via the list. This overall brings the time from 16 sec. spent in __iadd__ to 9 sec. in __iadd__. Another possible solution for all this is to have a internal structure of CompileArgs of trees, so you have the "basic" layer of arguments where the position does not matter. Additionally, you have two stacks of lists, the pre stack and the post stack, duplicates can then be checked when itereting, which would safe another ~4s in terms of efl. However, i do not have time for this undertaking right now.
Diffstat (limited to 'mesonbuild/compilers/compilers.py')
-rw-r--r--mesonbuild/compilers/compilers.py33
1 files changed, 26 insertions, 7 deletions
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 37cf2e0..2a29716 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -15,6 +15,7 @@
import contextlib, os.path, re, tempfile
import collections.abc
import typing as T
+from functools import lru_cache
from ..linkers import StaticLinker, GnuLikeDynamicLinkerMixin, SolarisDynamicLinker
from .. import coredata
@@ -445,6 +446,9 @@ class CompilerArgs(collections.abc.MutableSequence):
iterable: T.Optional[T.Iterable[str]] = None):
self.compiler = compiler
self.__container = list(iterable) if iterable is not None else [] # type: T.List[str]
+ self.__seen_args = set()
+ for arg in self.__container:
+ self.__seen_args.add(arg)
@T.overload # noqa: F811
def __getitem__(self, index: int) -> str: # noqa: F811
@@ -467,20 +471,27 @@ class CompilerArgs(collections.abc.MutableSequence):
def __setitem__(self, index, value) -> None: # noqa: F811
self.__container[index] = value
+ for v in value:
+ self.__seen_args.add(v)
def __delitem__(self, index: T.Union[int, slice]) -> None:
+ value = self.__container[index]
del self.__container[index]
+ if value in self.__seen_args and value in self.__container: # this is also honoring that you can have duplicated entries
+ self.__seen_args.remove(value)
def __len__(self) -> int:
return len(self.__container)
def insert(self, index: int, value: str) -> None:
self.__container.insert(index, value)
+ self.__seen_args.add(value)
def copy(self) -> 'CompilerArgs':
return CompilerArgs(self.compiler, self.__container.copy())
@classmethod
+ @lru_cache(maxsize=None)
def _can_dedup(cls, arg):
'''
Returns whether the argument can be safely de-duped. This is dependent
@@ -526,6 +537,7 @@ class CompilerArgs(collections.abc.MutableSequence):
return 0
@classmethod
+ @lru_cache(maxsize=None)
def _should_prepend(cls, arg):
if arg.startswith(cls.prepend_prefixes):
return True
@@ -588,6 +600,7 @@ class CompilerArgs(collections.abc.MutableSequence):
self.append(arg)
else:
self.__container.append(arg)
+ self.__seen_args.add(arg)
def extend_direct(self, iterable: T.Iterable[str]) -> None:
'''
@@ -619,6 +632,7 @@ class CompilerArgs(collections.abc.MutableSequence):
Add two CompilerArgs while taking into account overriding of arguments
and while preserving the order of arguments as much as possible
'''
+ this_round_added = set() # a dict that contains a value, when the value was added this round
pre = [] # type: T.List[str]
post = [] # type: T.List[str]
if not isinstance(args, collections.abc.Iterable):
@@ -630,20 +644,25 @@ class CompilerArgs(collections.abc.MutableSequence):
dedup = self._can_dedup(arg)
if dedup == 1:
# Argument already exists and adding a new instance is useless
- if arg in self or arg in pre or arg in post:
+ if arg in self.__seen_args or arg in pre or arg in post:
continue
+ should_prepend = self._should_prepend(arg)
if dedup == 2:
# Remove all previous occurrences of the arg and add it anew
- if arg in self:
+ if arg in self.__seen_args and arg not in this_round_added: #if __seen_args contains arg as well as this_round_added, then its not yet part in self.
self.remove(arg)
- if arg in pre:
- pre.remove(arg)
- if arg in post:
- post.remove(arg)
- if self._should_prepend(arg):
+ if should_prepend:
+ if arg in pre:
+ pre.remove(arg)
+ else:
+ if arg in post:
+ post.remove(arg)
+ if should_prepend:
pre.append(arg)
else:
post.append(arg)
+ self.__seen_args.add(arg)
+ this_round_added.add(arg)
# Insert at the beginning
self[:0] = pre
# Append to the end