Skip to content

Instantly share code, notes, and snippets.

@pythoninthegrass
Last active January 19, 2023 00:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pythoninthegrass/5bfa98505bf232d593f76bc638ca295f to your computer and use it in GitHub Desktop.
Save pythoninthegrass/5bfa98505bf232d593f76bc638ca295f to your computer and use it in GitHub Desktop.
Profile .bashrc
#!/usr/bin/env python
import argparse
import io
import operator
import re
from contextlib import redirect_stderr
from pathlib import Path
"""
# SOURCES
https://www.rosipov.com/blog/profiling-slow-bashrc/
https://mdjnewman.me/2017/10/debugging-slow-bash-startup-files/
# USAGE
## Add to top of .bashrc:
# .bashrc profiling start
exec 5> >(ts -i "%.s" >> /tmp/bashrc.log)
export BASH_XTRACEFD=5
PS4=":${BASH_SOURCE[0]##*/}:$LINENO+"; set -x
## End of .bashrc
# .bashrc profiling end
set +x
## Run
./bashprofile.py /tmp/bashrc.log -n 20
"""
# TODO: prog exits when using args; set in `launch.json`
# parse args
parser = argparse.ArgumentParser(description='Analyze bashrc log for speed.', exit_on_error=False)
parser.add_argument('filename', help='Default: /tmp/bashrc.log')
parser.add_argument('-n', default=20, help='number of results to show')
try:
f = io.StringIO()
with redirect_stderr(f):
args = parser.parse_args()
filename, n = args.filename, int(args.n)
except SystemExit:
filename = Path('/tmp/bashrc.log')
n = 20
# analyse log with timestamps starting with "0.000010"
with open(filename, 'r') as f:
q = {}
for line in f.readlines():
# replace `:` until `.bashrc` is found (negative lookbehind)
line = re.sub(r"(?<!.bashrc)\:+", '', line)
# replace `+` from `.bashrc:21+string` (negative lookahead)
line = re.sub(r"(?<!.bashrc)\+", ' ', line)
# split line between time and `.bashrc:21 command`
## e.g., 0.000013 .bashrc:21 alias 'dotdrop=dotdrop --cfg=/Users/lance.stephens/dotfiles/config.yaml'
words = line.split(maxsplit=1)
time = float(words[0].split()[0])
value = words[-1]
q[time] = value
# TODO: fix sorting not being descending order
# sort dict by time descending (key needs to be float)
od = dict(sorted(q.items(), key=operator.itemgetter(0)))
# print all with time > 0.1s
print('[time > 0.1s]')
for k, v in od.items():
if k > 0.1:
print(k, v)
# print top n
print(f"[top {n}]")
for k, v in od.items():
if n > 0:
print(k, v)
n -= 1
else:
break
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment