mirror of
https://github.com/luau-lang/luau.git
synced 2024-11-15 14:25:44 +08:00
95 lines
3.7 KiB
Python
95 lines
3.7 KiB
Python
#!usr/bin/python3
|
|
"""
|
|
To use this command, simply run the command:
|
|
`command script import /path/to/your/game-engine/Client/Luau/tools/stackdbg.py`
|
|
in the `lldb` interpreter. You can also add it to your .lldbinit file to have it be
|
|
automatically imported.
|
|
|
|
If using vscode, you can add the above command to your launch.json under `preRunCommands` for the appropriate target. For example:
|
|
{
|
|
"name": "Luau.UnitTest",
|
|
"type": "lldb",
|
|
"request": "launch",
|
|
"program": "${workspaceFolder}/build/ninja/common-tests/noopt/Luau/Luau.UnitTest",
|
|
"preRunCommands": [
|
|
"command script import ${workspaceFolder}/Client/Luau/tools/stackdbg.py"
|
|
],
|
|
}
|
|
|
|
Once this is loaded,
|
|
`(lldb) help stack`
|
|
or
|
|
`(lldb) stack -h
|
|
or
|
|
`(lldb) stack --help
|
|
|
|
can get you started
|
|
"""
|
|
|
|
import lldb
|
|
import functools
|
|
import argparse
|
|
import shlex
|
|
|
|
# Dumps the collected frame data
|
|
def dump(collected):
|
|
for (frame_name, size_in_kb, live_size_kb, variables) in collected:
|
|
print(f'{frame_name}, locals: {size_in_kb}kb, fp-sp: {live_size_kb}kb')
|
|
for (var_name, var_size, variable_obj) in variables:
|
|
print(f' {var_name}, {var_size} bytes')
|
|
|
|
def dbg_stack_pressure(frame, frames_to_show = 5, sort_frames = False, vars_to_show = 5, sort_vars = True):
|
|
totalKb = 0
|
|
collect = []
|
|
for f in frame.thread:
|
|
frame_name = f.GetFunctionName()
|
|
variables = [ (v.GetName(), v.GetByteSize(), v) for v in f.get_locals() ]
|
|
if sort_vars:
|
|
variables.sort(key = lambda x: x[1], reverse = True)
|
|
size_in_kb = functools.reduce(lambda x,y : x + y[1], variables, 0) / 1024
|
|
|
|
fp = f.GetFP()
|
|
sp = f.GetSP()
|
|
live_size_kb = round((fp - sp) / 1024, 2)
|
|
|
|
size_in_kb = round(size_in_kb, 2)
|
|
totalKb += size_in_kb
|
|
collect.append((frame_name, size_in_kb, live_size_kb, variables[:vars_to_show]))
|
|
if sort_frames:
|
|
collect.sort(key = lambda x: x[1], reverse = True)
|
|
|
|
print("******************** Report Stack Usage ********************")
|
|
totalMb = round(totalKb / 1024, 2)
|
|
print(f'{len(frame.thread)} stack frames used {totalMb}MB')
|
|
dump(collect[:frames_to_show])
|
|
|
|
def stack(debugger, command, result, internal_dict):
|
|
"""
|
|
usage: [-h] [-f FRAMES] [-fd] [-v VARS] [-vd]
|
|
|
|
optional arguments:
|
|
-h, --help show this help message and exit
|
|
-f FRAMES, --frames FRAMES
|
|
How many stack frames to display
|
|
-fd, --sort_frames Sort frames
|
|
-v VARS, --vars VARS How many variables per frame to display
|
|
-vd, --sort_vars Sort frames
|
|
"""
|
|
|
|
frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
|
|
args = shlex.split(command)
|
|
argparser = argparse.ArgumentParser(allow_abbrev = True)
|
|
argparser.add_argument("-f", "--frames", required=False, help="How many stack frames to display", default=5, type=int)
|
|
argparser.add_argument("-fd", "--sort_frames", required=False, help="Sort frames in descending order of stack usage", action="store_true", default=False)
|
|
argparser.add_argument("-v", "--vars", required=False, help="How many variables per frame to display", default=5, type=int)
|
|
argparser.add_argument("-vd", "--sort_vars", required=False, help="Sort locals in descending order of stack usage ", action="store_true", default=False)
|
|
|
|
args = argparser.parse_args(args)
|
|
dbg_stack_pressure(frame, frames_to_show=args.frames, sort_frames=args.sort_frames, vars_to_show=args.vars, sort_vars=args.sort_vars)
|
|
|
|
# Initialization code to add commands
|
|
def __lldb_init_module(debugger, internal_dict):
|
|
debugger.HandleCommand('command script add -f stackdbg.stack stack')
|
|
print("The 'stack' python command has been installed and is ready for use.")
|
|
|