Profiling is easy now :)
This commit is contained in:
parent
f134c5752b
commit
dd4324bad4
|
@ -371,50 +371,17 @@ def runCmd(args: cli.Args):
|
|||
os.environ["CK_BUILDDIR"] = product.target.builddir
|
||||
os.environ["CK_COMPONENT"] = product.component.id
|
||||
|
||||
if debug:
|
||||
if debugger == "lldb":
|
||||
shell.exec(
|
||||
"lldb",
|
||||
*(("-o", "b main") if wait else ()),
|
||||
*("-o", "run"),
|
||||
str(product.path),
|
||||
*args.extra,
|
||||
)
|
||||
elif debugger == "gdb":
|
||||
shell.exec(
|
||||
"gdb",
|
||||
*(("-ex", "b main") if wait else ()),
|
||||
*("-ex", "run"),
|
||||
str(product.path),
|
||||
*args.extra,
|
||||
)
|
||||
try:
|
||||
command = [str(product.path), *args.extra]
|
||||
|
||||
if debug:
|
||||
shell.debug(command, debugger=debugger, wait=wait)
|
||||
elif profile:
|
||||
shell.profile(command)
|
||||
else:
|
||||
raise RuntimeError(f"Unknown debugger {debugger}")
|
||||
elif profile:
|
||||
# Profile the executable using perf
|
||||
shell.exec(
|
||||
"perf",
|
||||
"record",
|
||||
"-g",
|
||||
"-o",
|
||||
"perf.data",
|
||||
"--call-graph",
|
||||
"dwarf",
|
||||
str(object=product.path),
|
||||
*args.extra,
|
||||
)
|
||||
|
||||
# Run this command using subprocess
|
||||
# perf script -i perf.data | speedscope -
|
||||
import subprocess
|
||||
|
||||
proc = subprocess.Popen(
|
||||
["perf", "script", "-i", "perf.data"], stdout=subprocess.PIPE
|
||||
)
|
||||
subprocess.run(["speedscope", "-"], stdin=proc.stdout)
|
||||
proc.wait()
|
||||
else:
|
||||
shell.exec(str(product.path), *args.extra)
|
||||
shell.exec(*command)
|
||||
except Exception as e:
|
||||
cli.error(e)
|
||||
|
||||
|
||||
@cli.command("t", "builder/test", "Run all test targets")
|
||||
|
|
|
@ -24,6 +24,7 @@ GLOBAL_CK_DIR = os.path.join(os.path.expanduser("~"), ".cutekit")
|
|||
BUILD_DIR = os.path.join(PROJECT_CK_DIR, "build")
|
||||
CACHE_DIR = os.path.join(PROJECT_CK_DIR, "cache")
|
||||
EXTERN_DIR = os.path.join(PROJECT_CK_DIR, "extern")
|
||||
TMP_DIR = os.path.join(PROJECT_CK_DIR, "tmp")
|
||||
SRC_DIR = "src"
|
||||
META_DIR = "meta"
|
||||
TARGETS_DIR = os.path.join(META_DIR, "targets")
|
||||
|
|
|
@ -69,14 +69,15 @@ def combineMixins(*mixins: Mixin) -> Mixin:
|
|||
mixins: dict[str, Mixin] = {
|
||||
"cache": mixinCache,
|
||||
"debug": mixinDebug,
|
||||
"asan": makeMixinSan("address"),
|
||||
"asan": combineMixins(makeMixinSan("address"), makeMixinSan("leak")),
|
||||
"msan": makeMixinSan("memory"),
|
||||
"tsan": makeMixinSan("thread"),
|
||||
"ubsan": makeMixinSan("undefined"),
|
||||
"sanitize": combineMixins(
|
||||
"lsan": makeMixinSan("leak"),
|
||||
"san": combineMixins(
|
||||
makeMixinSan("address"),
|
||||
makeMixinSan("memory"),
|
||||
makeMixinSan("thread"),
|
||||
makeMixinSan("undefined"),
|
||||
makeMixinSan("leak"),
|
||||
),
|
||||
"tune": makeMixinTune("native"),
|
||||
"release": combineMixins(
|
||||
|
|
|
@ -12,6 +12,7 @@ import logging
|
|||
import tempfile
|
||||
import dataclasses as dt
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from . import const
|
||||
|
||||
|
@ -134,6 +135,7 @@ def wget(url: str, path: Optional[str] = None) -> str:
|
|||
|
||||
def exec(*args: str, quiet: bool = False, cwd: Optional[str] = None) -> bool:
|
||||
_logger.debug(f"Executing {args}")
|
||||
cmdName = Path(args[0]).name
|
||||
|
||||
try:
|
||||
proc = subprocess.run(
|
||||
|
@ -156,34 +158,86 @@ def exec(*args: str, quiet: bool = False, cwd: Optional[str] = None) -> bool:
|
|||
raise RuntimeError(f"{args[0]}: Command not found")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
raise RuntimeError(f"{args[0]}: Interrupted")
|
||||
raise RuntimeError(f"{cmdName}: Interrupted")
|
||||
|
||||
if proc.returncode == -signal.SIGSEGV:
|
||||
raise RuntimeError(f"{args[0]}: Segmentation fault")
|
||||
raise RuntimeError(f"{cmdName}: Segmentation fault")
|
||||
|
||||
if proc.returncode != 0:
|
||||
raise RuntimeError(f"{args[0]}: Process exited with code {proc.returncode}")
|
||||
raise RuntimeError(f"{cmdName}: Process exited with code {proc.returncode}")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def popen(*args: str) -> str:
|
||||
_logger.debug(f"Executing {args}")
|
||||
_logger.debug(f"Executing {args}...")
|
||||
|
||||
cmdName = Path(args[0]).name
|
||||
|
||||
try:
|
||||
proc = subprocess.run(args, stdout=subprocess.PIPE, stderr=sys.stderr)
|
||||
except FileNotFoundError:
|
||||
raise RuntimeError(f"{args[0]}: Command not found")
|
||||
raise RuntimeError(f"{cmdName}: Command not found")
|
||||
|
||||
if proc.returncode == -signal.SIGSEGV:
|
||||
raise RuntimeError(f"{args[0]}: Segmentation fault")
|
||||
raise RuntimeError(f"{cmdName}: Segmentation fault")
|
||||
|
||||
if proc.returncode != 0:
|
||||
raise RuntimeError(f"{args[0]}: Process exited with code {proc.returncode}")
|
||||
raise RuntimeError(f"{cmdName}: Process exited with code {proc.returncode}")
|
||||
|
||||
return proc.stdout.decode("utf-8").strip()
|
||||
|
||||
|
||||
def debug(cmd: list[str], debugger: str = "lldb", wait: bool = False):
|
||||
if debugger == "lldb":
|
||||
exec(
|
||||
"lldb",
|
||||
*(("-o", "b main") if wait else ()),
|
||||
*("-o", "run"),
|
||||
*cmd,
|
||||
)
|
||||
elif debugger == "gdb":
|
||||
exec(
|
||||
"gdb",
|
||||
*(("-ex", "b main") if wait else ()),
|
||||
*("-ex", "run"),
|
||||
*cmd,
|
||||
)
|
||||
else:
|
||||
raise RuntimeError(f"Unknown debugger {debugger}")
|
||||
|
||||
|
||||
def profile(cmd: list[str]):
|
||||
mkdir(const.TMP_DIR)
|
||||
perfFile = f"{const.TMP_DIR}/perf.data"
|
||||
try:
|
||||
exec(
|
||||
"perf",
|
||||
"record",
|
||||
"-g",
|
||||
"-o",
|
||||
perfFile,
|
||||
"--call-graph",
|
||||
"dwarf",
|
||||
*cmd,
|
||||
)
|
||||
except Exception as e:
|
||||
if not os.path.exists(perfFile):
|
||||
raise e
|
||||
|
||||
try:
|
||||
proc = subprocess.Popen(
|
||||
["perf", "script", "-i", perfFile], stdout=subprocess.PIPE
|
||||
)
|
||||
subprocess.run(["speedscope", "-"], stdin=proc.stdout)
|
||||
proc.wait()
|
||||
except Exception as e:
|
||||
rmrf(perfFile)
|
||||
raise e
|
||||
|
||||
rmrf(perfFile)
|
||||
|
||||
|
||||
def readdir(path: str) -> list[str]:
|
||||
_logger.debug(f"Reading directory {path}")
|
||||
|
||||
|
|
Loading…
Reference in a new issue