feat: playlist shuffle, lazy resolution, TTS ducking, kept repair
Some checks failed
Some checks failed
Music: - #random URL fragment shuffles playlist tracks before enqueuing - Lazy playlist resolution: first 10 tracks resolve immediately, remaining are fetched in a background task - !kept repair re-downloads kept tracks with missing local files - !kept shows [MISSING] marker for tracks without local files - TTS ducking: music ducks when merlin speaks via voice peer, smooth restore after TTS finishes Performance (from profiling): - Connection pool: preload_content=True for SOCKS connection reuse - Pool tuning: 30 pools / 8 connections (up from 20/4) - _PooledResponse wrapper for stdlib-compatible read interface - Iterative _extract_videos (replace 51K-deep recursion with stack) - proxy=False for local SearXNG Voice + multi-bot: - Per-bot voice config lookup ([<username>.voice] in TOML) - Mute detection: skip duck silence when all users muted - Autoplay shuffle deck (no repeats until full cycle) - Seek clamp to track duration (prevent seek-past-end stall) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
97
tools/profile
Executable file
97
tools/profile
Executable file
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env bash
|
||||
# Analyze cProfile data from the bot process.
|
||||
# Usage: tools/profile [OPTIONS] [FILE]
|
||||
#
|
||||
# Options:
|
||||
# -n NUM Show top NUM entries (default: 30)
|
||||
# -s SORT Sort by: cumtime, tottime, calls, name (default: cumtime)
|
||||
# -f PATTERN Filter to entries matching PATTERN
|
||||
# -c Callers view (who calls the hot functions)
|
||||
# -h Show this help
|
||||
#
|
||||
# Examples:
|
||||
# tools/profile # top 30 by cumulative time
|
||||
# tools/profile -s tottime -n 20 # top 20 by total time
|
||||
# tools/profile -f mumble # only mumble-related functions
|
||||
# tools/profile -c -f stream_audio # who calls stream_audio
|
||||
# tools/profile data/old.prof # analyze a specific file
|
||||
|
||||
# shellcheck source=tools/_common.sh
|
||||
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/_common.sh"
|
||||
|
||||
DEFAULT_PROF="$PROJECT_DIR/data/derp.prof"
|
||||
TOP=30
|
||||
SORT="cumtime"
|
||||
PATTERN=""
|
||||
CALLERS=false
|
||||
|
||||
usage() {
|
||||
sed -n '2,/^$/s/^# \?//p' "$0"
|
||||
exit 0
|
||||
}
|
||||
|
||||
while getopts ":n:s:f:ch" opt; do
|
||||
case $opt in
|
||||
n) TOP="$OPTARG" ;;
|
||||
s) SORT="$OPTARG" ;;
|
||||
f) PATTERN="$OPTARG" ;;
|
||||
c) CALLERS=true ;;
|
||||
h) usage ;;
|
||||
:) err "option -$OPTARG requires an argument"; exit 2 ;;
|
||||
*) err "unknown option -$OPTARG"; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
PROF="${1:-$DEFAULT_PROF}"
|
||||
|
||||
if [[ ! -f "$PROF" ]]; then
|
||||
err "profile not found: $PROF"
|
||||
dim "run the bot with --cprofile and stop it gracefully"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validate sort key
|
||||
case "$SORT" in
|
||||
cumtime|tottime|calls|name) ;;
|
||||
*) err "invalid sort key: $SORT (use cumtime, tottime, calls, name)"; exit 2 ;;
|
||||
esac
|
||||
|
||||
# Profile metadata
|
||||
size=$(stat -c %s "$PROF" 2>/dev/null || stat -f %z "$PROF" 2>/dev/null)
|
||||
human=$(numfmt --to=iec-i --suffix=B "$size" 2>/dev/null || echo "${size}B")
|
||||
modified=$(stat -c %y "$PROF" 2>/dev/null | cut -d. -f1)
|
||||
|
||||
printf '%b%s%b\n' "$BLU" "Profile" "$RST"
|
||||
dim "$PROF ($human, $modified)"
|
||||
echo
|
||||
|
||||
# Build pstats script
|
||||
read -r -d '' PYSCRIPT << 'PYEOF' || true
|
||||
import pstats
|
||||
import sys
|
||||
import io
|
||||
|
||||
prof_path = sys.argv[1]
|
||||
sort_key = sys.argv[2]
|
||||
top_n = int(sys.argv[3])
|
||||
pattern = sys.argv[4]
|
||||
callers = sys.argv[5] == "1"
|
||||
|
||||
p = pstats.Stats(prof_path, stream=sys.stdout)
|
||||
p.strip_dirs()
|
||||
p.sort_stats(sort_key)
|
||||
|
||||
if pattern:
|
||||
if callers:
|
||||
p.print_callers(pattern, top_n)
|
||||
else:
|
||||
p.print_stats(pattern, top_n)
|
||||
else:
|
||||
if callers:
|
||||
p.print_callers(top_n)
|
||||
else:
|
||||
p.print_stats(top_n)
|
||||
PYEOF
|
||||
|
||||
exec python3 -c "$PYSCRIPT" "$PROF" "$SORT" "$TOP" "$PATTERN" "$( $CALLERS && echo 1 || echo 0 )"
|
||||
Reference in New Issue
Block a user