Sprinkle functools.lru_cache() in a few more places

This improves the backend generation time for gst-build from 7.4s to
6.6s. This is probably all the low-hanging fruit we can get, further
improvements will probably require refactoring, moving to pathlib.Path
or reimplementing CompilerArgs:

   222045    0.551    0.000    1.324    0.000 compilers.py:666(__iadd__)
     3691    0.230    0.000    0.885    0.000 ninjabackend.py:99(write)
   233560    0.441    0.000    0.701    0.000 posixpath.py:75(join)
      882    0.141    0.000    0.636    0.001 backends.py:509(generate_basic_compiler_args)
   256301    0.248    0.000    0.576    0.000 compilers.py:562(_can_dedup)
    37369    0.035    0.000    0.466    0.000 compilers.py:652(extend_direct)
    74650    0.067    0.000    0.431    0.000 compilers.py:641(append_direct)
   158153    0.089    0.000    0.405    0.000 ninjabackend.py:129(<lambda>)
      845    0.064    0.000    0.391    0.000 ninjabackend.py:279(get_target_generated_sources)
    58161    0.070    0.000    0.317    0.000 backends.py:217(get_target_generated_dir)
   216825    0.175    0.000    0.275    0.000 ninjabackend.py:48(ninja_quote)
      845    0.058    0.000    0.255    0.000 ninjabackend.py:2289(guess_external_link_dependencies)
      845    0.068    0.000    0.239    0.000 backends.py:793(get_custom_target_provided_libraries)
    52101    0.030    0.000    0.237    0.000 compilers.py:716(append)
  1319326    0.231    0.000    0.231    0.000 {built-in method builtins.isinstance}
  1189117    0.229    0.000    0.229    0.000 {method 'startswith' of 'str' objects}
     3235    0.102    0.000    0.228    0.000 compilers.py:614(to_native)

Note: there are 845 build targets.
pull/3993/head
Nirbheek Chauhan 7 years ago committed by Nirbheek Chauhan
parent d67ec95b50
commit 1af704a509
  1. 3
      mesonbuild/backend/backends.py
  2. 13
      mesonbuild/backend/ninjabackend.py
  3. 19
      mesonbuild/compilers/c.py
  4. 10
      mesonbuild/compilers/compilers.py
  5. 22
      run_unittests.py

@ -17,7 +17,6 @@ from .. import build
from .. import dependencies
from .. import mesonlib
from .. import mlog
from .. import compilers
import json
import subprocess
from ..mesonlib import MesonException, OrderedSet
@ -400,7 +399,7 @@ class Backend:
result = OrderedSet()
result.add('meson-out')
result.update(self.rpaths_for_bundled_shared_libraries(target))
return list(result)
return tuple(result)
def object_filename_from_source(self, target, source):
assert isinstance(source, mesonlib.File)

@ -20,6 +20,7 @@ import subprocess
from collections import OrderedDict
import itertools
from pathlib import PurePath
from functools import lru_cache
from . import backends
from .. import modules
@ -147,7 +148,6 @@ class NinjaBackend(backends.Backend):
super().__init__(build)
self.name = 'ninja'
self.ninja_filename = 'build.ninja'
self.target_arg_cache = {}
self.fortran_deps = {}
self.all_outputs = {}
@ -1951,6 +1951,7 @@ rule FORTRAN_DEP_HACK%s
incs += compiler.get_include_args(i, False)
return incs
@lru_cache(maxsize=None)
def _generate_single_compile(self, target, compiler, is_generated=False):
base_proxy = self.get_base_options_for_target(target)
# Create an empty commands list, and start adding arguments from
@ -2047,12 +2048,7 @@ rule FORTRAN_DEP_HACK%s
raise AssertionError('BUG: sources should not contain headers {!r}'.format(src))
compiler = get_compiler_for_source(target.compilers.values(), src)
key = (target, compiler, is_generated)
if key in self.target_arg_cache:
commands = self.target_arg_cache[key]
else:
commands = self._generate_single_compile(target, compiler, is_generated)
self.target_arg_cache[key] = commands
commands = self._generate_single_compile(target, compiler, is_generated)
commands = CompilerArgs(commands.compiler, commands)
build_dir = self.environment.get_build_dir()
@ -2276,6 +2272,7 @@ rule FORTRAN_DEP_HACK%s
return linker.get_link_whole_for(target_args) if len(target_args) else []
@staticmethod
@lru_cache(maxsize=None)
def guess_library_absolute_path(linker, libname, search_dirs, patterns):
for d in search_dirs:
for p in patterns:
@ -2334,7 +2331,7 @@ rule FORTRAN_DEP_HACK%s
guessed_dependencies = []
# TODO The get_library_naming requirement currently excludes link targets that use d or fortran as their main linker
if hasattr(linker, 'get_library_naming'):
search_dirs = list(search_dirs) + linker.get_library_dirs(self.environment)
search_dirs = tuple(search_dirs) + linker.get_library_dirs(self.environment)
static_patterns = linker.get_library_naming(self.environment, 'static', strict=True)
shared_patterns = linker.get_library_naming(self.environment, 'shared', strict=True)
for libname in libs:

@ -119,6 +119,7 @@ class CCompiler(Compiler):
return None, fname
# The default behavior is this, override in MSVC
@functools.lru_cache(maxsize=None)
def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
if self.id == 'clang' and self.clang_type == compilers.CLANG_OSX:
return self.build_osx_rpath_args(build_dir, rpath_paths, build_rpath)
@ -222,7 +223,7 @@ class CCompiler(Compiler):
p = Path(p)
if p.exists():
paths.append(p.resolve().as_posix())
return paths
return tuple(paths)
def get_compiler_dirs(self, env, name):
'''
@ -232,23 +233,19 @@ class CCompiler(Compiler):
for line in stdo.split('\n'):
if line.startswith(name + ':'):
return CCompiler._split_fetch_real_dirs(line.split('=', 1)[1])
return []
return ()
@functools.lru_cache()
def get_library_dirs(self, env):
key = (tuple(self.exelist), env)
if key not in self.library_dirs_cache:
self.library_dirs_cache[key] = self.get_compiler_dirs(env, 'libraries')
return self.library_dirs_cache[key][:]
return self.get_compiler_dirs(env, 'libraries')
@functools.lru_cache()
def get_program_dirs(self, env):
'''
Programs used by the compiler. Also where toolchain DLLs such as
libstdc++-6.dll are found with MinGW.
'''
key = (tuple(self.exelist), env)
if key not in self.program_dirs_cache:
self.program_dirs_cache[key] = self.get_compiler_dirs(env, 'programs')
return self.program_dirs_cache[key][:]
return self.get_compiler_dirs(env, 'programs')
def get_pic_args(self):
return ['-fPIC']
@ -907,7 +904,7 @@ class CCompiler(Compiler):
patterns += self._get_patterns(env, prefixes, stlibext, False)
else:
raise AssertionError('BUG: unknown libtype {!r}'.format(libtype))
return patterns
return tuple(patterns)
@staticmethod
def _sort_shlibs_openbsd(libs):

@ -923,7 +923,7 @@ class Compiler:
raise EnvironmentException('Language {} does not support library finding.'.format(self.get_display_language()))
def get_library_dirs(self, *args, **kwargs):
return []
return ()
def has_multi_arguments(self, args, env):
raise EnvironmentException(
@ -1381,12 +1381,12 @@ class ElbrusCompiler(GnuCompiler):
os_env = os.environ.copy()
os_env['LC_ALL'] = 'C'
stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=os_env)[1]
paths = []
paths = ()
for line in stdo.split('\n'):
if line.startswith('libraries:'):
# lcc does not include '=' in --print-search-dirs output.
libstr = line.split(' ', 1)[1]
paths = [os.path.realpath(p) for p in libstr.split(':')]
paths = (os.path.realpath(p) for p in libstr.split(':'))
break
return paths
@ -1394,12 +1394,12 @@ class ElbrusCompiler(GnuCompiler):
os_env = os.environ.copy()
os_env['LC_ALL'] = 'C'
stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=os_env)[1]
paths = []
paths = ()
for line in stdo.split('\n'):
if line.startswith('programs:'):
# lcc does not include '=' in --print-search-dirs output.
libstr = line.split(' ', 1)[1]
paths = [os.path.realpath(p) for p in libstr.split(':')]
paths = (os.path.realpath(p) for p in libstr.split(':'))
break
return paths

@ -575,22 +575,22 @@ class InternalTests(unittest.TestCase):
'''
Unit test for the library search patterns used by find_library()
'''
unix_static = ['lib{}.a', '{}.a']
msvc_static = ['lib{}.a', 'lib{}.lib', '{}.a', '{}.lib']
unix_static = ('lib{}.a', '{}.a')
msvc_static = ('lib{}.a', 'lib{}.lib', '{}.a', '{}.lib')
# This is the priority list of pattern matching for library searching
patterns = {'openbsd': {'shared': ['lib{}.so', '{}.so', 'lib{}.so.[0-9]*.[0-9]*'],
patterns = {'openbsd': {'shared': ('lib{}.so', '{}.so', 'lib{}.so.[0-9]*.[0-9]*'),
'static': unix_static},
'linux': {'shared': ['lib{}.so', '{}.so'],
'linux': {'shared': ('lib{}.so', '{}.so'),
'static': unix_static},
'darwin': {'shared': ['lib{}.dylib', '{}.dylib'],
'darwin': {'shared': ('lib{}.dylib', '{}.dylib'),
'static': unix_static},
'cygwin': {'shared': ['cyg{}.dll', 'cyg{}.dll.a', 'lib{}.dll',
'lib{}.dll.a', '{}.dll', '{}.dll.a'],
'static': ['cyg{}.a'] + unix_static},
'windows-msvc': {'shared': ['lib{}.lib', '{}.lib'],
'cygwin': {'shared': ('cyg{}.dll', 'cyg{}.dll.a', 'lib{}.dll',
'lib{}.dll.a', '{}.dll', '{}.dll.a'),
'static': ('cyg{}.a',) + unix_static},
'windows-msvc': {'shared': ('lib{}.lib', '{}.lib'),
'static': msvc_static},
'windows-mingw': {'shared': ['lib{}.dll.a', 'lib{}.lib', 'lib{}.dll',
'{}.dll.a', '{}.lib', '{}.dll'],
'windows-mingw': {'shared': ('lib{}.dll.a', 'lib{}.lib', 'lib{}.dll',
'{}.dll.a', '{}.lib', '{}.dll'),
'static': msvc_static}}
env = get_fake_env('', '', '')
cc = env.detect_c_compiler(False)

Loading…
Cancel
Save