summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2023-01-21 19:31:43 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2023-01-24 21:59:44 +0000
commit663c259ffa3b013cb7cc3f4e1dc69aca917706b2 (patch)
treed828d1a205d688dad358f1864e57905460ac80bd
parent72072db00465595293eda7b9b5446fcabef6552a (diff)
downloadpoky-663c259ffa3b013cb7cc3f4e1dc69aca917706b2.tar.gz
bitbake: data: Add support for new BB_HASH_CODEPARSER_VALS for cache optimisation
Currently the codeparser cache ends up being extended for every parse run since there are values in the functions such as the result of os.getpid() from LOGFIFO in OE-Core. Digging into that issue, there are also lots of similar but different functions being parsed where the change might just be a path to WORKDIR, a change in PN or PV or something like DATE/TIME. There is no reason we have to use these changing values when computing the dependenies of the functions. Even with a small tweak like: BB_HASH_CODEPARSER_VALS = "LOGFIFO=/ T=/ WORKDIR=/ DATE=1234 TIME=1234 PV=0.0-1 PN=nopn" the cache is reduced from ~4.6MB, increasing by ~300kb for every parse run to around 1.3MB and remaining static for oe-core and meta-oe. In my local build, admittedly heavily experimented with, the cache had grown to 120MB. The benefits of doing this are: * faster load time for bitbake since the cache is smaller to read from disk and load into memory * being able to skip saving the cache upon shutdown * lower memory footprint for bitbake * faster codeparser data lookups (since there is less data to search) We only use these special values when passing code fragments to the codeparser to parse so the real variable values should otherwise be used in the hash data. The overall effect of this change, combined with others to avoid saving unchanged cache files can be ~2s on a ~16s parse on my local system and results in a more responsive feeling bitbake. It also allows parsing performance to be investigated more consistently. (Bitbake rev: f24bbaaddb36f479a59a958e7fc90ef454c19473) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--bitbake/lib/bb/data.py15
-rw-r--r--bitbake/lib/bb/tests/codeparser.py14
2 files changed, 17 insertions, 12 deletions
diff --git a/bitbake/lib/bb/data.py b/bitbake/lib/bb/data.py
index 841369699e..f3ae062022 100644
--- a/bitbake/lib/bb/data.py
+++ b/bitbake/lib/bb/data.py
@@ -261,7 +261,7 @@ def emit_func_python(func, o=sys.__stdout__, d = init()):
261 newdeps |= set((d.getVarFlag(dep, "vardeps") or "").split()) 261 newdeps |= set((d.getVarFlag(dep, "vardeps") or "").split())
262 newdeps -= seen 262 newdeps -= seen
263 263
264def build_dependencies(key, keys, mod_funcs, shelldeps, varflagsexcl, ignored_vars, d): 264def build_dependencies(key, keys, mod_funcs, shelldeps, varflagsexcl, ignored_vars, d, codeparsedata):
265 def handle_contains(value, contains, exclusions, d): 265 def handle_contains(value, contains, exclusions, d):
266 newvalue = [] 266 newvalue = []
267 if value: 267 if value:
@@ -312,14 +312,14 @@ def build_dependencies(key, keys, mod_funcs, shelldeps, varflagsexcl, ignored_va
312 value = varflags.get("vardepvalue") 312 value = varflags.get("vardepvalue")
313 elif varflags.get("func"): 313 elif varflags.get("func"):
314 if varflags.get("python"): 314 if varflags.get("python"):
315 value = d.getVarFlag(key, "_content", False) 315 value = codeparsedata.getVarFlag(key, "_content", False)
316 parser = bb.codeparser.PythonParser(key, logger) 316 parser = bb.codeparser.PythonParser(key, logger)
317 parser.parse_python(value, filename=varflags.get("filename"), lineno=varflags.get("lineno")) 317 parser.parse_python(value, filename=varflags.get("filename"), lineno=varflags.get("lineno"))
318 deps = deps | parser.references 318 deps = deps | parser.references
319 deps = deps | (keys & parser.execs) 319 deps = deps | (keys & parser.execs)
320 value = handle_contains(value, parser.contains, exclusions, d) 320 value = handle_contains(value, parser.contains, exclusions, d)
321 else: 321 else:
322 value, parsedvar = d.getVarFlag(key, "_content", False, retparser=True) 322 value, parsedvar = codeparsedata.getVarFlag(key, "_content", False, retparser=True)
323 parser = bb.codeparser.ShellParser(key, logger) 323 parser = bb.codeparser.ShellParser(key, logger)
324 parser.parse_shell(parsedvar.value) 324 parser.parse_shell(parsedvar.value)
325 deps = deps | shelldeps 325 deps = deps | shelldeps
@@ -378,12 +378,17 @@ def generate_dependencies(d, ignored_vars):
378 shelldeps = set(key for key in d.getVar("__exportlist", False) if d.getVarFlag(key, "export", False) and not d.getVarFlag(key, "unexport", False)) 378 shelldeps = set(key for key in d.getVar("__exportlist", False) if d.getVarFlag(key, "export", False) and not d.getVarFlag(key, "unexport", False))
379 varflagsexcl = d.getVar('BB_SIGNATURE_EXCLUDE_FLAGS') 379 varflagsexcl = d.getVar('BB_SIGNATURE_EXCLUDE_FLAGS')
380 380
381 codeparserd = d.createCopy()
382 for forced in (d.getVar('BB_HASH_CODEPARSER_VALS') or "").split():
383 key, value = forced.split("=", 1)
384 codeparserd.setVar(key, value)
385
381 deps = {} 386 deps = {}
382 values = {} 387 values = {}
383 388
384 tasklist = d.getVar('__BBTASKS', False) or [] 389 tasklist = d.getVar('__BBTASKS', False) or []
385 for task in tasklist: 390 for task in tasklist:
386 deps[task], values[task] = build_dependencies(task, keys, mod_funcs, shelldeps, varflagsexcl, ignored_vars, d) 391 deps[task], values[task] = build_dependencies(task, keys, mod_funcs, shelldeps, varflagsexcl, ignored_vars, d, codeparserd)
387 newdeps = deps[task] 392 newdeps = deps[task]
388 seen = set() 393 seen = set()
389 while newdeps: 394 while newdeps:
@@ -392,7 +397,7 @@ def generate_dependencies(d, ignored_vars):
392 newdeps = set() 397 newdeps = set()
393 for dep in nextdeps: 398 for dep in nextdeps:
394 if dep not in deps: 399 if dep not in deps:
395 deps[dep], values[dep] = build_dependencies(dep, keys, mod_funcs, shelldeps, varflagsexcl, ignored_vars, d) 400 deps[dep], values[dep] = build_dependencies(dep, keys, mod_funcs, shelldeps, varflagsexcl, ignored_vars, d, codeparserd)
396 newdeps |= deps[dep] 401 newdeps |= deps[dep]
397 newdeps -= seen 402 newdeps -= seen
398 #print "For %s: %s" % (task, str(deps[task])) 403 #print "For %s: %s" % (task, str(deps[task]))
diff --git a/bitbake/lib/bb/tests/codeparser.py b/bitbake/lib/bb/tests/codeparser.py
index a508f23bcb..7f5d59ca74 100644
--- a/bitbake/lib/bb/tests/codeparser.py
+++ b/bitbake/lib/bb/tests/codeparser.py
@@ -318,7 +318,7 @@ d.getVar(a(), False)
318 "filename": "example.bb", 318 "filename": "example.bb",
319 }) 319 })
320 320
321 deps, values = bb.data.build_dependencies("FOO", set(self.d.keys()), set(), set(), set(), set(), self.d) 321 deps, values = bb.data.build_dependencies("FOO", set(self.d.keys()), set(), set(), set(), set(), self.d, self.d)
322 322
323 self.assertEqual(deps, set(["somevar", "bar", "something", "inexpand", "test", "test2", "a"])) 323 self.assertEqual(deps, set(["somevar", "bar", "something", "inexpand", "test", "test2", "a"]))
324 324
@@ -365,7 +365,7 @@ esac
365 self.d.setVarFlags("FOO", {"func": True}) 365 self.d.setVarFlags("FOO", {"func": True})
366 self.setEmptyVars(execs) 366 self.setEmptyVars(execs)
367 367
368 deps, values = bb.data.build_dependencies("FOO", set(self.d.keys()), set(), set(), set(), set(), self.d) 368 deps, values = bb.data.build_dependencies("FOO", set(self.d.keys()), set(), set(), set(), set(), self.d, self.d)
369 369
370 self.assertEqual(deps, set(["somevar", "inverted"] + execs)) 370 self.assertEqual(deps, set(["somevar", "inverted"] + execs))
371 371
@@ -375,7 +375,7 @@ esac
375 self.d.setVar("FOO", "foo=oe_libinstall; eval $foo") 375 self.d.setVar("FOO", "foo=oe_libinstall; eval $foo")
376 self.d.setVarFlag("FOO", "vardeps", "oe_libinstall") 376 self.d.setVarFlag("FOO", "vardeps", "oe_libinstall")
377 377
378 deps, values = bb.data.build_dependencies("FOO", set(self.d.keys()), set(), set(), set(), set(), self.d) 378 deps, values = bb.data.build_dependencies("FOO", set(self.d.keys()), set(), set(), set(), set(), self.d, self.d)
379 379
380 self.assertEqual(deps, set(["oe_libinstall"])) 380 self.assertEqual(deps, set(["oe_libinstall"]))
381 381
@@ -384,7 +384,7 @@ esac
384 self.d.setVar("FOO", "foo=oe_libinstall; eval $foo") 384 self.d.setVar("FOO", "foo=oe_libinstall; eval $foo")
385 self.d.setVarFlag("FOO", "vardeps", "${@'oe_libinstall'}") 385 self.d.setVarFlag("FOO", "vardeps", "${@'oe_libinstall'}")
386 386
387 deps, values = bb.data.build_dependencies("FOO", set(self.d.keys()), set(), set(), set(), set(), self.d) 387 deps, values = bb.data.build_dependencies("FOO", set(self.d.keys()), set(), set(), set(), set(), self.d, self.d)
388 388
389 self.assertEqual(deps, set(["oe_libinstall"])) 389 self.assertEqual(deps, set(["oe_libinstall"]))
390 390
@@ -399,7 +399,7 @@ esac
399 # Check dependencies 399 # Check dependencies
400 self.d.setVar('ANOTHERVAR', expr) 400 self.d.setVar('ANOTHERVAR', expr)
401 self.d.setVar('TESTVAR', 'anothervalue testval testval2') 401 self.d.setVar('TESTVAR', 'anothervalue testval testval2')
402 deps, values = bb.data.build_dependencies("ANOTHERVAR", set(self.d.keys()), set(), set(), set(), set(), self.d) 402 deps, values = bb.data.build_dependencies("ANOTHERVAR", set(self.d.keys()), set(), set(), set(), set(), self.d, self.d)
403 self.assertEqual(sorted(values.splitlines()), 403 self.assertEqual(sorted(values.splitlines()),
404 sorted([expr, 404 sorted([expr,
405 'TESTVAR{anothervalue} = Set', 405 'TESTVAR{anothervalue} = Set',
@@ -418,14 +418,14 @@ esac
418 self.d.setVar('ANOTHERVAR', varval) 418 self.d.setVar('ANOTHERVAR', varval)
419 self.d.setVar('TESTVAR', 'anothervalue testval testval2') 419 self.d.setVar('TESTVAR', 'anothervalue testval testval2')
420 self.d.setVar('TESTVAR2', 'testval3') 420 self.d.setVar('TESTVAR2', 'testval3')
421 deps, values = bb.data.build_dependencies("ANOTHERVAR", set(self.d.keys()), set(), set(), set(), set(["TESTVAR"]), self.d) 421 deps, values = bb.data.build_dependencies("ANOTHERVAR", set(self.d.keys()), set(), set(), set(), set(["TESTVAR"]), self.d, self.d)
422 self.assertEqual(sorted(values.splitlines()), sorted([varval])) 422 self.assertEqual(sorted(values.splitlines()), sorted([varval]))
423 self.assertEqual(deps, set(["TESTVAR2"])) 423 self.assertEqual(deps, set(["TESTVAR2"]))
424 self.assertEqual(self.d.getVar('ANOTHERVAR').split(), ['testval3', 'anothervalue']) 424 self.assertEqual(self.d.getVar('ANOTHERVAR').split(), ['testval3', 'anothervalue'])
425 425
426 # Check the vardepsexclude flag is handled by contains functionality 426 # Check the vardepsexclude flag is handled by contains functionality
427 self.d.setVarFlag('ANOTHERVAR', 'vardepsexclude', 'TESTVAR') 427 self.d.setVarFlag('ANOTHERVAR', 'vardepsexclude', 'TESTVAR')
428 deps, values = bb.data.build_dependencies("ANOTHERVAR", set(self.d.keys()), set(), set(), set(), set(), self.d) 428 deps, values = bb.data.build_dependencies("ANOTHERVAR", set(self.d.keys()), set(), set(), set(), set(), self.d, self.d)
429 self.assertEqual(sorted(values.splitlines()), sorted([varval])) 429 self.assertEqual(sorted(values.splitlines()), sorted([varval]))
430 self.assertEqual(deps, set(["TESTVAR2"])) 430 self.assertEqual(deps, set(["TESTVAR2"]))
431 self.assertEqual(self.d.getVar('ANOTHERVAR').split(), ['testval3', 'anothervalue']) 431 self.assertEqual(self.d.getVar('ANOTHERVAR').split(), ['testval3', 'anothervalue'])