oe-build-perf-test 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #!/usr/bin/python3
  2. #
  3. # Build performance test script
  4. #
  5. # Copyright (c) 2016, Intel Corporation.
  6. #
  7. # This program is free software; you can redistribute it and/or modify it
  8. # under the terms and conditions of the GNU General Public License,
  9. # version 2, as published by the Free Software Foundation.
  10. #
  11. # This program is distributed in the hope it will be useful, but WITHOUT
  12. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  14. # more details.
  15. #
  16. """Build performance test script"""
  17. import argparse
  18. import errno
  19. import fcntl
  20. import logging
  21. import os
  22. import shutil
  23. import sys
  24. import unittest
  25. from datetime import datetime
  26. sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '/lib')
  27. import scriptpath
  28. scriptpath.add_oe_lib_path()
  29. import oeqa.buildperf
  30. from oeqa.buildperf import (BuildPerfTestLoader, BuildPerfTestResult,
  31. BuildPerfTestRunner, KernelDropCaches)
  32. from oeqa.utils.commands import runCmd
  33. # Set-up logging
  34. LOG_FORMAT = '[%(asctime)s] %(levelname)s: %(message)s'
  35. logging.basicConfig(level=logging.INFO, format=LOG_FORMAT)
  36. log = logging.getLogger()
  37. def acquire_lock(lock_f):
  38. """Acquire flock on file"""
  39. log.debug("Acquiring lock %s", os.path.abspath(lock_f.name))
  40. try:
  41. fcntl.flock(lock_f, fcntl.LOCK_EX | fcntl.LOCK_NB)
  42. except IOError as err:
  43. if err.errno == errno.EAGAIN:
  44. return False
  45. raise
  46. log.debug("Lock acquired")
  47. return True
  48. def pre_run_sanity_check():
  49. """Sanity check of build environment"""
  50. build_dir = os.environ.get("BUILDDIR")
  51. if not build_dir:
  52. log.error("BUILDDIR not set. Please run the build environmnent setup "
  53. "script.")
  54. return False
  55. if os.getcwd() != build_dir:
  56. log.error("Please run this script under BUILDDIR (%s)", build_dir)
  57. return False
  58. ret = runCmd('which bitbake', ignore_status=True)
  59. if ret.status:
  60. log.error("bitbake command not found")
  61. return False
  62. return True
  63. def setup_file_logging(log_file):
  64. """Setup loggin to file"""
  65. log_dir = os.path.dirname(log_file)
  66. if not os.path.exists(log_dir):
  67. os.makedirs(log_dir)
  68. formatter = logging.Formatter(LOG_FORMAT)
  69. handler = logging.FileHandler(log_file)
  70. handler.setFormatter(formatter)
  71. log.addHandler(handler)
  72. def archive_build_conf(out_dir):
  73. """Archive build/conf to test results"""
  74. src_dir = os.path.join(os.environ['BUILDDIR'], 'conf')
  75. tgt_dir = os.path.join(out_dir, 'build', 'conf')
  76. os.makedirs(os.path.dirname(tgt_dir))
  77. shutil.copytree(src_dir, tgt_dir)
  78. def parse_args(argv):
  79. """Parse command line arguments"""
  80. parser = argparse.ArgumentParser(
  81. formatter_class=argparse.ArgumentDefaultsHelpFormatter)
  82. parser.add_argument('-D', '--debug', action='store_true',
  83. help='Enable debug level logging')
  84. parser.add_argument('--globalres-file',
  85. help="Append results to 'globalres' csv file")
  86. parser.add_argument('--lock-file', default='./oe-build-perf.lock',
  87. metavar='FILENAME',
  88. help="Lock file to use")
  89. parser.add_argument('-o', '--out-dir', default='results-{date}',
  90. help="Output directory for test results")
  91. return parser.parse_args(argv)
  92. def main(argv=None):
  93. """Script entry point"""
  94. args = parse_args(argv)
  95. if args.debug:
  96. log.setLevel(logging.DEBUG)
  97. lock_f = open(args.lock_file, 'w')
  98. if not acquire_lock(lock_f):
  99. log.error("Another instance of this script is running, exiting...")
  100. return 1
  101. if not pre_run_sanity_check():
  102. return 1
  103. # Check our capability to drop caches and ask pass if needed
  104. KernelDropCaches.check()
  105. # Load build perf tests
  106. loader = BuildPerfTestLoader()
  107. suite = loader.discover(start_dir=os.path.dirname(oeqa.buildperf.__file__))
  108. # Set-up log file
  109. out_dir = args.out_dir.format(date=datetime.now().strftime('%Y%m%d%H%M%S'))
  110. setup_file_logging(os.path.join(out_dir, 'output.log'))
  111. archive_build_conf(out_dir)
  112. runner = BuildPerfTestRunner(out_dir, verbosity=2)
  113. # Suppress logger output to stderr so that the output from unittest
  114. # is not mixed with occasional logger output
  115. log.handlers[0].setLevel(logging.CRITICAL)
  116. # Run actual tests
  117. result = runner.run(suite)
  118. # Restore logger output to stderr
  119. log.handlers[0].setLevel(log.level)
  120. if result.wasSuccessful():
  121. if args.globalres_file:
  122. result.update_globalres_file(args.globalres_file)
  123. return 0
  124. return 1
  125. if __name__ == '__main__':
  126. sys.exit(main())