add profiling startup import check and testcase to count it

pull/11907/head
Eli Schwartz 2 years ago
parent 25f5f3554d
commit 620bdf5895
No known key found for this signature in database
GPG Key ID: CEB167EFB5722BD6
  1. 28
      mesonbuild/msetup.py
  2. 277
      test cases/unit/113 empty project/expected_mods.json
  3. 1
      test cases/unit/113 empty project/meson.build
  4. 27
      unittests/platformagnostictests.py

@ -13,25 +13,14 @@
# limitations under the License.
from __future__ import annotations
import typing as T
import time
import sys
import datetime
import os.path
import platform
import argparse, datetime, glob, json, os, platform, shutil, sys, tempfile, time
import cProfile as profile
import argparse
import tempfile
import shutil
import glob
from pathlib import Path
import typing as T
from . import environment, interpreter, mesonlib
from . import build
from . import mlog, coredata
from . import mintro
from .mesonlib import MesonException, MachineChoice
from . import build, coredata, environment, interpreter, mesonlib, mintro, mlog
from .dependencies import PkgConfigDependency
from .mesonlib import MachineChoice, MesonException
git_ignore_file = '''# This file is autogenerated by Meson. If you change or delete it, it won't be recreated.
*
@ -291,6 +280,15 @@ class MesonApp:
'Please consider using `meson devenv` instead. See https://github.com/mesonbuild/meson/pull/9243 '
'for details.')
if self.options.profile:
fname = os.path.join(self.build_dir, 'meson-logs', 'profile-startup-modules.json')
mods = set(sys.modules.keys())
mesonmods = {mod for mod in mods if (mod+'.').startswith('mesonbuild.')}
stdmods = sorted(mods - mesonmods)
data = {'stdlib': {'modules': stdmods, 'count': len(stdmods)}, 'meson': {'modules': sorted(mesonmods), 'count': len(mesonmods)}}
with open(fname, 'w', encoding='utf-8') as f:
json.dump(data, f)
except Exception as e:
mintro.write_meson_info_file(b, [e])
if cdf is not None:

@ -0,0 +1,277 @@
{
"stdlib": {
"modules": [
"__future__",
"__main__",
"_abc",
"_ast",
"_bisect",
"_blake2",
"_bz2",
"_codecs",
"_collections",
"_collections_abc",
"_compat_pickle",
"_compression",
"_datetime",
"_frozen_importlib",
"_frozen_importlib_external",
"_functools",
"_hashlib",
"_imp",
"_io",
"_json",
"_locale",
"_lsprof",
"_lzma",
"_opcode",
"_operator",
"_pickle",
"_posixsubprocess",
"_random",
"_sha512",
"_signal",
"_sitebuiltins",
"_socket",
"_sre",
"_ssl",
"_stat",
"_string",
"_struct",
"_thread",
"_uuid",
"_warnings",
"_weakref",
"_weakrefset",
"abc",
"argparse",
"array",
"ast",
"base64",
"binascii",
"bisect",
"builtins",
"bz2",
"cProfile",
"calendar",
"codecs",
"collections",
"collections.abc",
"configparser",
"contextlib",
"copy",
"copyreg",
"dataclasses",
"datetime",
"dis",
"email",
"email._encoded_words",
"email._parseaddr",
"email._policybase",
"email.base64mime",
"email.charset",
"email.encoders",
"email.errors",
"email.feedparser",
"email.header",
"email.iterators",
"email.message",
"email.parser",
"email.quoprimime",
"email.utils",
"encodings",
"encodings.aliases",
"encodings.utf_8",
"enum",
"errno",
"fcntl",
"fnmatch",
"functools",
"genericpath",
"gettext",
"glob",
"hashlib",
"http",
"http.client",
"importlib",
"importlib._abc",
"importlib._adapters",
"importlib._bootstrap",
"importlib._bootstrap_external",
"importlib._common",
"importlib.abc",
"importlib.machinery",
"importlib.resources",
"inspect",
"io",
"itertools",
"json",
"json.decoder",
"json.encoder",
"json.scanner",
"keyword",
"linecache",
"locale",
"lzma",
"marshal",
"math",
"netrc",
"ntpath",
"opcode",
"operator",
"os",
"os.path",
"pathlib",
"pickle",
"platform",
"posix",
"posixpath",
"profile",
"quopri",
"random",
"re",
"reprlib",
"select",
"selectors",
"shlex",
"shutil",
"signal",
"site",
"socket",
"sre_compile",
"sre_constants",
"sre_parse",
"ssl",
"stat",
"string",
"struct",
"subprocess",
"sys",
"tempfile",
"textwrap",
"threading",
"time",
"token",
"tokenize",
"types",
"typing",
"typing.io",
"typing.re",
"urllib",
"urllib.error",
"urllib.parse",
"urllib.request",
"urllib.response",
"uu",
"uuid",
"warnings",
"weakref",
"zipimport",
"zlib"
],
"count": 167
},
"meson": {
"modules": [
"mesonbuild",
"mesonbuild._pathlib",
"mesonbuild.arglist",
"mesonbuild.ast",
"mesonbuild.ast.interpreter",
"mesonbuild.ast.introspection",
"mesonbuild.ast.postprocess",
"mesonbuild.ast.printer",
"mesonbuild.ast.visitor",
"mesonbuild.backend",
"mesonbuild.backend.backends",
"mesonbuild.backend.ninjabackend",
"mesonbuild.build",
"mesonbuild.cmake",
"mesonbuild.cmake.common",
"mesonbuild.cmake.executor",
"mesonbuild.cmake.fileapi",
"mesonbuild.cmake.generator",
"mesonbuild.cmake.interpreter",
"mesonbuild.cmake.toolchain",
"mesonbuild.cmake.traceparser",
"mesonbuild.cmake.tracetargets",
"mesonbuild.compilers",
"mesonbuild.compilers.compilers",
"mesonbuild.compilers.detect",
"mesonbuild.coredata",
"mesonbuild.dependencies",
"mesonbuild.dependencies.base",
"mesonbuild.dependencies.boost",
"mesonbuild.dependencies.cmake",
"mesonbuild.dependencies.coarrays",
"mesonbuild.dependencies.configtool",
"mesonbuild.dependencies.cuda",
"mesonbuild.dependencies.detect",
"mesonbuild.dependencies.dev",
"mesonbuild.dependencies.dub",
"mesonbuild.dependencies.factory",
"mesonbuild.dependencies.framework",
"mesonbuild.dependencies.hdf5",
"mesonbuild.dependencies.misc",
"mesonbuild.dependencies.mpi",
"mesonbuild.dependencies.pkgconfig",
"mesonbuild.dependencies.platform",
"mesonbuild.dependencies.python",
"mesonbuild.dependencies.qt",
"mesonbuild.dependencies.scalapack",
"mesonbuild.dependencies.ui",
"mesonbuild.depfile",
"mesonbuild.envconfig",
"mesonbuild.environment",
"mesonbuild.interpreter",
"mesonbuild.interpreter.compiler",
"mesonbuild.interpreter.dependencyfallbacks",
"mesonbuild.interpreter.interpreter",
"mesonbuild.interpreter.interpreterobjects",
"mesonbuild.interpreter.mesonmain",
"mesonbuild.interpreter.primitives",
"mesonbuild.interpreter.primitives.array",
"mesonbuild.interpreter.primitives.boolean",
"mesonbuild.interpreter.primitives.dict",
"mesonbuild.interpreter.primitives.integer",
"mesonbuild.interpreter.primitives.range",
"mesonbuild.interpreter.primitives.string",
"mesonbuild.interpreter.type_checking",
"mesonbuild.interpreterbase",
"mesonbuild.interpreterbase._unholder",
"mesonbuild.interpreterbase.baseobjects",
"mesonbuild.interpreterbase.decorators",
"mesonbuild.interpreterbase.disabler",
"mesonbuild.interpreterbase.exceptions",
"mesonbuild.interpreterbase.helpers",
"mesonbuild.interpreterbase.interpreterbase",
"mesonbuild.interpreterbase.operator",
"mesonbuild.linkers",
"mesonbuild.linkers.detect",
"mesonbuild.linkers.linkers",
"mesonbuild.mesondata",
"mesonbuild.mesonlib",
"mesonbuild.mesonmain",
"mesonbuild.mintro",
"mesonbuild.mlog",
"mesonbuild.modules",
"mesonbuild.modules.gnome",
"mesonbuild.mparser",
"mesonbuild.msetup",
"mesonbuild.optinterpreter",
"mesonbuild.programs",
"mesonbuild.scripts",
"mesonbuild.scripts.gettext",
"mesonbuild.scripts.meson_exe",
"mesonbuild.utils",
"mesonbuild.utils.core",
"mesonbuild.utils.platform",
"mesonbuild.utils.posix",
"mesonbuild.utils.universal",
"mesonbuild.utils.vsenv",
"mesonbuild.wrap",
"mesonbuild.wrap.wrap"
],
"count": 98
}
}

@ -206,6 +206,9 @@ class PlatformAgnosticTests(BasePlatformTests):
output. The script will print all python modules loaded and we verify
that it contains only an acceptable subset. Loading too many modules
slows down the build when many custom targets get wrapped.
This list must not be edited without a clear rationale for why it is
acceptable to do so!
'''
es = ExecutableSerialisation(python_command + ['-c', 'exit(0)'], env=EnvironmentVariables())
p = Path(self.builddir, 'exe.dat')
@ -227,3 +230,27 @@ class PlatformAgnosticTests(BasePlatformTests):
'mesonbuild.scripts.test_loaded_modules'
]
self.assertEqual(sorted(expected_meson_modules), sorted(meson_modules))
def test_setup_loaded_modules(self):
'''
Execute a very basic meson.build and capture a list of all python
modules loaded. We verify that it contains only an acceptable subset.
Loading too many modules slows down `meson setup` startup time and
gives a perception that meson is slow.
Adding more modules to the default startup flow is not an unreasonable
thing to do as new features are added, but keeping track of them is
good.
'''
testdir = os.path.join(self.unit_test_dir, '113 empty project')
self.init(testdir)
self._run(self.meson_command + ['--internal', 'regenerate', '--profile-self', testdir, self.builddir])
with open(os.path.join(self.builddir, 'meson-logs', 'profile-startup-modules.json')) as f:
data = json.load(f)['meson']
with open(os.path.join(testdir, 'expected_mods.json')) as f:
expected = json.load(f)['meson']['modules']
self.assertEqual(data['modules'], expected)
self.assertEqual(data['count'], 98)

Loading…
Cancel
Save