TypePHP 编译器
https://swoole.com/aot/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
6.1 KiB
212 lines
6.1 KiB
#!/usr/bin/env bash
|
|
|
|
# Collect low-frequency host and process metrics while preserving the observed
|
|
# command's stdout, stderr, and exit status.
|
|
|
|
set -u
|
|
|
|
if [[ $# -lt 3 ]]; then
|
|
echo "Usage: $0 <output-directory> -- <command> [arguments ...]" >&2
|
|
exit 2
|
|
fi
|
|
if [[ $2 != "--" ]]; then
|
|
echo "Usage: $0 <output-directory> -- <command> [arguments ...]" >&2
|
|
exit 2
|
|
fi
|
|
|
|
output_dir=$1
|
|
shift 2
|
|
mkdir -p "${output_dir}"
|
|
|
|
metadata_file="${output_dir}/environment.txt"
|
|
samples_file="${output_dir}/resources.log"
|
|
processes_file="${output_dir}/processes.log"
|
|
memory_maps_file="${output_dir}/tpc-memory.log"
|
|
time_file="${output_dir}/command-time.txt"
|
|
disk_file="${output_dir}/disk-usage.txt"
|
|
|
|
cgroup_dir=/sys/fs/cgroup
|
|
if [[ -r /proc/self/cgroup ]]; then
|
|
cgroup_v2_path=$(awk -F: '$1 == "0" { print $3; exit }' /proc/self/cgroup)
|
|
if [[ -n ${cgroup_v2_path} && -d /sys/fs/cgroup${cgroup_v2_path} ]]; then
|
|
cgroup_dir=/sys/fs/cgroup${cgroup_v2_path}
|
|
fi
|
|
fi
|
|
|
|
write_environment() {
|
|
{
|
|
echo "timestamp_utc=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
echo "runner_image=${ImageOS:-unknown}"
|
|
echo "runner_image_version=${ImageVersion:-unknown}"
|
|
echo "runner_arch=${RUNNER_ARCH:-unknown}"
|
|
echo "workspace=${GITHUB_WORKSPACE:-$PWD}"
|
|
echo
|
|
uname -a
|
|
echo
|
|
lscpu
|
|
echo
|
|
free -b
|
|
echo
|
|
df -B1 -T . /tmp
|
|
echo
|
|
ulimit -a
|
|
echo
|
|
cat /proc/self/cgroup
|
|
echo
|
|
echo "cgroup_directory=${cgroup_dir}"
|
|
for source in \
|
|
"${cgroup_dir}/cpu.max" \
|
|
"${cgroup_dir}/cpuset.cpus.effective" \
|
|
"${cgroup_dir}/memory.max" \
|
|
"${cgroup_dir}/memory.swap.max" \
|
|
"${cgroup_dir}/pids.max"; do
|
|
if [[ -r ${source} ]]; then
|
|
echo "${source}=$(cat "${source}")"
|
|
fi
|
|
done
|
|
echo
|
|
sed -n -E '/^(MemTotal|MemFree|MemAvailable|Buffers|Cached|SwapCached|SwapTotal|SwapFree|Dirty|Writeback|AnonPages|Mapped|Slab|SReclaimable|PageTables):/p' /proc/meminfo
|
|
} >"${metadata_file}" 2>&1
|
|
}
|
|
|
|
write_binary_details() {
|
|
local binary=${TYPEPHP_OBSERVED_BINARY:-./tpc}
|
|
local details_file="${output_dir}/binary.txt"
|
|
|
|
{
|
|
echo "path=${binary}"
|
|
stat "${binary}"
|
|
echo
|
|
file "${binary}"
|
|
echo
|
|
size -A "${binary}"
|
|
echo
|
|
readelf -lW "${binary}"
|
|
echo
|
|
ldd "${binary}"
|
|
} >"${details_file}" 2>&1 || true
|
|
}
|
|
|
|
write_resource_sample() {
|
|
local label=$1
|
|
local source
|
|
|
|
{
|
|
echo "===== ${label} $(date -u +%Y-%m-%dT%H:%M:%SZ) ====="
|
|
echo "loadavg=$(cat /proc/loadavg)"
|
|
sed -n '1p' /proc/stat
|
|
free -b
|
|
df -B1 . /tmp
|
|
|
|
for source in /proc/pressure/cpu /proc/pressure/memory /proc/pressure/io; do
|
|
if [[ -r ${source} ]]; then
|
|
echo "--- ${source}"
|
|
cat "${source}"
|
|
fi
|
|
done
|
|
|
|
echo "--- /proc/meminfo"
|
|
sed -n -E '/^(MemFree|MemAvailable|Buffers|Cached|SwapCached|SwapFree|Dirty|Writeback|AnonPages|Mapped|Slab|SReclaimable|PageTables):/p' /proc/meminfo
|
|
|
|
echo "--- /proc/vmstat"
|
|
sed -n -E '/^(pgfault|pgmajfault|pswpin|pswpout|pgscan_[^ ]+|pgsteal_[^ ]+|workingset_refault_[^ ]+|nr_dirty|nr_writeback) /p' /proc/vmstat
|
|
|
|
for source in \
|
|
"${cgroup_dir}/cpu.stat" \
|
|
"${cgroup_dir}/cpu.pressure" \
|
|
"${cgroup_dir}/memory.current" \
|
|
"${cgroup_dir}/memory.peak" \
|
|
"${cgroup_dir}/memory.events" \
|
|
"${cgroup_dir}/memory.pressure" \
|
|
"${cgroup_dir}/io.stat" \
|
|
"${cgroup_dir}/io.pressure"; do
|
|
if [[ -r ${source} ]]; then
|
|
echo "--- ${source}"
|
|
cat "${source}"
|
|
fi
|
|
done
|
|
} >>"${samples_file}" 2>&1
|
|
|
|
{
|
|
echo "===== ${label} $(date -u +%Y-%m-%dT%H:%M:%SZ) ====="
|
|
ps -eo pid,ppid,etimes,pcpu,pmem,rss,vsz,min_flt,maj_flt,stat,comm --sort=-rss | head -n 31
|
|
} >>"${processes_file}" 2>&1
|
|
}
|
|
|
|
write_tpc_memory_sample() {
|
|
local label=$1
|
|
local pid
|
|
|
|
{
|
|
echo "===== ${label} $(date -u +%Y-%m-%dT%H:%M:%SZ) ====="
|
|
while read -r pid; do
|
|
[[ -n ${pid} ]] || continue
|
|
echo "--- pid=${pid}"
|
|
sed -n -E '/^(Name|Pid|PPid|VmPeak|VmSize|VmRSS|RssAnon|RssFile|RssShmem|VmSwap):/p' "/proc/${pid}/status" 2>/dev/null || true
|
|
sed -n -E '/^(Rss|Pss|Pss_Dirty|Shared_Clean|Shared_Dirty|Private_Clean|Private_Dirty|Anonymous|Swap):/p' "/proc/${pid}/smaps_rollup" 2>/dev/null || true
|
|
done < <(pgrep -x tpc 2>/dev/null || true)
|
|
} >>"${memory_maps_file}" 2>&1
|
|
}
|
|
|
|
write_disk_usage() {
|
|
local label=$1
|
|
|
|
{
|
|
echo "===== ${label} $(date -u +%Y-%m-%dT%H:%M:%SZ) ====="
|
|
if [[ -e ./tpc ]]; then
|
|
stat --format='tpc bytes=%s blocks=%b block_size=%B' ./tpc
|
|
fi
|
|
df -B1 -T . /tmp
|
|
} >>"${disk_file}" 2>&1
|
|
}
|
|
|
|
observed_pid=''
|
|
interrupted=0
|
|
|
|
forward_signal() {
|
|
interrupted=1
|
|
if [[ -n ${observed_pid} ]]; then
|
|
kill -TERM "${observed_pid}" 2>/dev/null || true
|
|
fi
|
|
}
|
|
|
|
trap forward_signal INT TERM
|
|
|
|
write_environment
|
|
write_binary_details
|
|
write_disk_usage before
|
|
write_resource_sample before
|
|
|
|
/usr/bin/time -v -o "${time_file}" -- "$@" &
|
|
observed_pid=$!
|
|
|
|
# Poll once per second so completion is delayed by at most one second. The
|
|
# expensive snapshot is taken only once every 20 seconds.
|
|
sample_count=0
|
|
while kill -0 "${observed_pid}" 2>/dev/null; do
|
|
sleep 1
|
|
sample_count=$((sample_count + 1))
|
|
if ((sample_count % 20 == 0)) && kill -0 "${observed_pid}" 2>/dev/null; then
|
|
write_resource_sample "sample-${sample_count}s"
|
|
fi
|
|
if ((sample_count % 60 == 0)) && kill -0 "${observed_pid}" 2>/dev/null; then
|
|
write_tpc_memory_sample "sample-${sample_count}s"
|
|
fi
|
|
done
|
|
|
|
wait "${observed_pid}"
|
|
status=$?
|
|
observed_pid=''
|
|
|
|
write_resource_sample after
|
|
write_disk_usage after
|
|
|
|
echo "Observed command resource summary:"
|
|
cat "${time_file}"
|
|
echo "Detailed samples: ${output_dir}"
|
|
|
|
if ((interrupted != 0)) && ((status == 0)); then
|
|
status=143
|
|
fi
|
|
|
|
exit "${status}"
|
|
|