mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Tools] (bench): clock profiles, bench sessions that release the perf stack's frequency caps, and a per-run frequency/thermal validity line.
This commit is contained in:
@@ -134,3 +134,24 @@ Reducers, all reading a probe directory:
|
||||
|
||||
The simpleperf reducers need `SIMPLEPERF_DIR` and a `binary_cache` from `binary_cache_builder.py`.
|
||||
Findings: `docs/Disaggregated/notes/perf-p15/PLAN-P15.md` section 2.
|
||||
|
||||
## Clocks, bench sessions and run validity (P15)
|
||||
|
||||
Every performance number carries the device state it was measured under.
|
||||
|
||||
- **`pin_clocks.sh`** pins CPU and GPU to a named profile (`PROFILE=sustained|gpumax|gpulow|cpulow|cpuhunt|gpuhunt`,
|
||||
see the script header; `sustained` is the default) and records it on the device.
|
||||
- **`bench_session.sh start|stop`**:
|
||||
- `start` records, then stops, the services that move frequency caps (`thermal-engine`, the QTI perf HAL,
|
||||
`vendor.perfservice`, Lenovo's `performance` and `hyperschedule_hal_service`). It releases their leftover
|
||||
requests in `/sys/kernel/msm_performance/parameters/cpu_{max,min}_freq`, which otherwise clamp
|
||||
`scaling_max_freq` under any pin, and then pins.
|
||||
- `stop` restarts every service that was running and verifies it is running again.
|
||||
- Wrap every device job so `stop` always runs (trap on EXIT/INT/TERM).
|
||||
- **`freq_sampler.sh`** runs on the device for each measurement window and samples every 2 s: CPU cur/max per
|
||||
policy, GPU cur, kgsl thermal level, busy and temperatures.
|
||||
- **`freqcheck.py`** decides VALID/INVALID against the intended pin (one OPP of tolerance, GPU checked while
|
||||
busy). Invalid runs are discarded and re-run after cool-down.
|
||||
- **`devstate.sh <outdir> [trace]`** writes the per-run `state.txt` line: profile and clocks, validity with the
|
||||
observed min/max frequencies and peak temperatures, daemons, MC version, swap interval and anland on/off.
|
||||
`fcl_probe.sh` and `matrix_p14.sh` (benchmark mode) call it.
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
# bench_session.sh start|stop|status - P15 measurement-validity rule, device side (Lenovo Y700, SM8650).
|
||||
#
|
||||
# start:
|
||||
# 1. records each frequency-moving service's prior state and the msm_performance requests
|
||||
# (/data/local/tmp/p15-bench-session, also echoed to the caller's log);
|
||||
# 2. stops those services: thermal-engine, the QTI perf HAL, the vendor perf service, Lenovo's
|
||||
# performance and hyperschedule services. Their requests OUTLIVE them: the perf stack's
|
||||
# game-mode levels land in /sys/kernel/msm_performance/parameters/cpu_{max,min}_freq, a
|
||||
# frequency QoS that clamps scaling_max_freq below any pin (measured 2026-10-08: 787 / 1286 /
|
||||
# 1075 / 1248 MHz on policies 0/2/5/7 while pin_clocks.sh believed it had pinned 2035 MHz);
|
||||
# 3. releases those requests and re-pins (pin_clocks.sh).
|
||||
# stop: starts every service that was running before start, and verifies each is running again.
|
||||
# ALWAYS run it - callers trap it on EXIT/INT/TERM, so an interrupted session restores too.
|
||||
# Kernel-level protection (LMh, BCL, kernel thermal trip points) is never touched; the run's sampler
|
||||
# (freq_sampler.sh -> freqcheck.py) shows any frequency collapse, and a collapse ends benchmarking.
|
||||
set -u
|
||||
export MSYS_NO_PATHCONV=1
|
||||
SER="${SER:-HA27Q3LQ}"
|
||||
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||||
SERVICES="${BENCH_STOP_SERVICES:-thermal-engine perf2-hal-1-0 vendor.perfservice performance hyperschedule_hal_service}"
|
||||
MARK=/data/local/tmp/p15-bench-session
|
||||
MP=/sys/kernel/msm_performance/parameters
|
||||
su_sh() { adb -s "$SER" shell "su -c '$1'"; }
|
||||
case "${1:-status}" in
|
||||
start)
|
||||
su_sh "if [ ! -f $MARK ]; then for s in $SERVICES; do echo svc \$s \$(getprop init.svc.\$s); done > $MARK; echo maxreq \$(cat $MP/cpu_max_freq) >> $MARK; echo minreq \$(cat $MP/cpu_min_freq) >> $MARK; fi; cat $MARK"
|
||||
su_sh "for s in $SERVICES; do setprop ctl.stop \$s; done"
|
||||
sleep 2
|
||||
su_sh "echo \"0:4294967295 1:4294967295 2:4294967295 3:4294967295 4:4294967295 5:4294967295 6:4294967295 7:4294967295\" > $MP/cpu_max_freq; echo \"0:0 1:0 2:0 3:0 4:0 5:0 6:0 7:0\" > $MP/cpu_min_freq"
|
||||
SER=$SER bash "$HERE/pin_clocks.sh" pin
|
||||
"$0" status ;;
|
||||
stop)
|
||||
su_sh "if [ -f $MARK ]; then grep \"^svc \" $MARK | while read k s st; do [ \"\$st\" = running ] && setprop ctl.start \$s; done; else for s in $SERVICES; do setprop ctl.start \$s; done; fi"
|
||||
sleep 3
|
||||
bad=$(su_sh "if [ -f $MARK ]; then grep \"^svc \" $MARK | while read k s st; do [ \"\$st\" = running ] && [ \"\$(getprop init.svc.\$s)\" != running ] && echo \$s; done; fi" | tr -d '\r')
|
||||
if [ -n "$bad" ]; then echo "bench_session: NOT RESTORED: $bad" >&2; exit 1; fi
|
||||
su_sh "rm -f $MARK"
|
||||
"$0" status ;;
|
||||
status)
|
||||
su_sh "for s in $SERVICES; do echo \$s=\$(getprop init.svc.\$s); done | tr '\n' ' '; echo; echo maxreq \$(cat $MP/cpu_max_freq)" ;;
|
||||
esac
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
# devstate.sh <outdir>: the one-line device state every reported number carries (P15 measurement rules).
|
||||
# Needs <outdir>/freq.txt + pin.txt (freq_sampler / pin_clocks show). Writes <outdir>/profile.txt,
|
||||
# <outdir>/valid.txt and <outdir>/state.txt, and prints the state line:
|
||||
# STATE profile=<name>(cpu/little/gpu MHz) <VALID|INVALID ... freqcheck summary> daemons=<..> swap=<..> anland=<on|off>
|
||||
set -u
|
||||
export MSYS_NO_PATHCONV=1
|
||||
out="$1"; kind="${2:-fcl}"; SER="${SER:-HA27Q3LQ}"; HERE="$(cd "$(dirname "$0")" && pwd)"
|
||||
FCL=com.tungsten.fcl.mgdebug.debug
|
||||
su_sh() { adb -s "$SER" shell "su -c '$1'"; }
|
||||
su_sh "cat /data/local/tmp/p15-bench-profile 2>/dev/null || echo profile=unpinned" | tr -d '\r' > "$out/profile.txt"
|
||||
python "$(cygpath -w "$HERE/freqcheck.py" 2>/dev/null || echo "$HERE/freqcheck.py")" "$(cygpath -w "$out/freq.txt")" "$(cygpath -w "$out/pin.txt")" > "$out/valid.txt" 2>&1
|
||||
daemons=$(su_sh "test -f /data/local/tmp/p15-bench-session && echo stopped\(\$(grep -c \"^svc \" /data/local/tmp/p15-bench-session)\) || echo running" | tr -d '\r')
|
||||
ver=$(adb -s "$SER" exec-out "su -c 'cat /data/data/$FCL/files/config.json'" 2>/dev/null | grep -o '"selectedMinecraftVersion": *"[^"][^"]*"' | head -1 | sed 's/.*: *"//; s/"$//')
|
||||
swap=$(su_sh "grep -h enableVsync /sdcard/FCL/.minecraft/versions/$ver/options.txt 2>/dev/null" | tr -d '\r' | sed 's/enableVsync://')
|
||||
anland=$(adb -s "$SER" shell pidof com.anland.consumer.mobilegl | tr -dc '0-9' | head -c 8)
|
||||
p=$(cat "$out/profile.txt")
|
||||
pn=$(echo "$p" | sed -n 's/.*profile=\([^ ]*\).*/\1/p'); pc=$(echo "$p" | sed -n 's/.*cpu=\([0-9]*\).*/\1/p'); pl=$(echo "$p" | sed -n 's/.*little=\([0-9]*\).*/\1/p'); pg=$(echo "$p" | sed -n 's/.*gpu=\([0-9]*\).*/\1/p')
|
||||
[ "$kind" = trace ] && { ver=-; swap=pbuffer; }
|
||||
line="STATE profile=${pn:-unpinned}(${pc:+$((pc/1000))/$((pl/1000))/$((pg/1000000))MHz}) $(head -1 "$out/valid.txt") daemons=$daemons mc=$ver swap=${swap:-?} anland=$([ -n "$anland" ] && echo on || echo off)"
|
||||
echo "$line" > "$out/state.txt"; echo "$line"
|
||||
@@ -36,6 +36,11 @@ echo "waited=$t ok=$ok attempt=$attempt" >> "$out/wait.txt"
|
||||
pid=$(adb -s $SER shell pidof $FCL | tr -d '\r' | awk '{print $NF}')
|
||||
echo "pid=$pid" >> "$out/wait.txt"
|
||||
snap() { adb -s $SER shell "su -c 'cat /proc/uptime; cat /sys/class/kgsl/kgsl-3d0/gpu_clock_stats; for t in /proc/$pid/task/*; do echo T \${t##*/} \$(cut -d\" \" -f1-3 \$t/schedstat) \$(cat \$t/comm); done'" > "$1"; }
|
||||
# P15 validity rule: frequency/thermal sampler for the whole measurement window (devstate.sh judges it)
|
||||
BENCH="$(cd "$(dirname "$0")" && pwd)"
|
||||
SER=$SER bash $BENCH/pin_clocks.sh show > "$out/pin.txt" 2>&1
|
||||
adb -s $SER push "$(cygpath -w $BENCH/freq_sampler.sh)" /data/local/tmp/p15-freq_sampler.sh >/dev/null
|
||||
su_sh "chmod 755 /data/local/tmp/p15-freq_sampler.sh; rm -f /data/local/tmp/p15freq.txt; (nohup sh /data/local/tmp/p15-freq_sampler.sh /data/local/tmp/p15freq.txt 2 >/dev/null 2>&1 &)"
|
||||
# A: ftrace
|
||||
EV=/sys/kernel/tracing/events
|
||||
su_sh "atrace --async_start -c -b 65536 -a $FCL gfx view sched freq >/dev/null 2>&1; for e in adreno_cmdbatch_submitted adreno_cmdbatch_retired kgsl_waittimestamp_entry kgsl_waittimestamp_exit adreno_syncobj_submitted adreno_syncobj_retired adreno_drawctxt_wait_start adreno_drawctxt_wait_done kgsl_timeline_wait; do echo 1 > $EV/kgsl/\$e/enable; done; echo 1 > $EV/sched/sched_waking/enable"
|
||||
@@ -52,6 +57,9 @@ if [ "$sp" = 1 ]; then
|
||||
su_sh "chmod 644 /data/local/tmp/p15perf.data"
|
||||
adb -s $SER pull /data/local/tmp/p15perf.data "$(cygpath -w "$out/perf.data")" >/dev/null
|
||||
fi
|
||||
su_sh "pkill -f p15-freq_sampler.sh; chmod 644 /data/local/tmp/p15freq.txt"
|
||||
adb -s $SER pull /data/local/tmp/p15freq.txt "$(cygpath -w "$out/freq.txt")" >/dev/null
|
||||
SER=$SER bash $BENCH/devstate.sh "$out"
|
||||
adb -s $SER logcat -d > "$out/logcat.txt"
|
||||
su_sh "am force-stop $FCL"
|
||||
grep -a "MobileGL fps:" "$out/logcat.txt" | tail -8 | sed 's/.*MobileGL fps: //' > "$out/fps.txt"
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/system/bin/sh
|
||||
# freq_sampler.sh <outfile> [period_s=2] - DEVICE-SIDE (pushed to /data/local/tmp, run as root in the
|
||||
# background for the length of one measurement, killed by the caller). One line per sample:
|
||||
# t=<uptime> c<policy>=<cur>/<max> ... gpu=<devfreq cur> gpuclk=<kgsl gpuclk> tpl=<thermal_pwrlevel>
|
||||
# thr=<throttling> busy=<gpu_busy_percentage> cpuT=<hottest cpu zone> gpuT=<hottest gpuss zone> skinT=<skin>
|
||||
# Cheap sysfs reads only, so the run it watches is not perturbed. freqcheck.py turns the file into
|
||||
# min/max/peak and a VALID/INVALID verdict (P15 measurement-validity rule).
|
||||
o=$1; p=${2:-2}; : > "$o"
|
||||
K=/sys/class/kgsl/kgsl-3d0
|
||||
zones=""
|
||||
for z in /sys/class/thermal/thermal_zone*; do
|
||||
case $(cat $z/type) in cpu-*|cpuss-*|gpuss-*|skin-msm-therm) zones="$zones $z";; esac
|
||||
done
|
||||
while :; do
|
||||
l="t=$(cut -d' ' -f1 /proc/uptime)"
|
||||
for c in /sys/devices/system/cpu/cpufreq/policy*; do
|
||||
l="$l c${c##*policy}=$(cat $c/scaling_cur_freq)/$(cat $c/scaling_max_freq)"
|
||||
done
|
||||
m=0; g=0; s=0
|
||||
for z in $zones; do
|
||||
v=$(cat $z/temp 2>/dev/null); [ -z "$v" ] && continue
|
||||
case $(cat $z/type) in cpu-*|cpuss-*) [ $v -gt $m ] && m=$v;; gpuss-*) [ $v -gt $g ] && g=$v;; skin-msm-therm) s=$v;; esac
|
||||
done
|
||||
echo "$l gpu=$(cat $K/devfreq/cur_freq) gpuclk=$(cat $K/gpuclk) tpl=$(cat $K/thermal_pwrlevel) thr=$(cat $K/throttling) busy=$(cat $K/gpu_busy_percentage | tr -d ' %') cpuT=$m gpuT=$g skinT=$s" >> "$o"
|
||||
sleep $p
|
||||
done
|
||||
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env python3
|
||||
"""freqcheck.py <freq.txt> [pin.txt] - P15 measurement-validity verdict for one run.
|
||||
|
||||
freq.txt is freq_sampler.sh output; pin.txt is the `pin_clocks.sh show` output taken when the
|
||||
session pinned (bench_session.sh writes it). A run is VALID only if every sample shows each CPU
|
||||
policy at its pinned frequency, with its scaling_max still at the pin (no cap), and - whenever the
|
||||
GPU is busy - the GPU at its pinned frequency, with no kgsl thermal power level or throttling.
|
||||
One OPP step of tolerance is allowed: the next available frequency below the pin.
|
||||
|
||||
Prints one line: VALID|INVALID, per-policy min/max cur freq, GPU min/max (busy samples), peak
|
||||
temperatures, and the reasons when invalid. Exit code 0 = valid, 1 = invalid, 2 = no samples.
|
||||
"""
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
def parse(path):
|
||||
rows = []
|
||||
for line in open(path, encoding="utf-8", errors="replace"):
|
||||
kv = dict(re.findall(r"(\w+)=([^\s]+)", line))
|
||||
if "t" in kv:
|
||||
rows.append(kv)
|
||||
return rows
|
||||
|
||||
|
||||
def pins(path):
|
||||
"""The INTENDED pin, from pin_clocks.sh's targets (env PIN_CPU_KHZ / PIN_LITTLE_KHZ / PIN_GPU_HZ,
|
||||
same defaults) mapped onto each policy's available frequencies - never the caps read back from
|
||||
the device, which a frequency daemon may already have lowered."""
|
||||
import os
|
||||
big = int(os.environ.get("PIN_CPU_KHZ", "2035200"))
|
||||
little = int(os.environ.get("PIN_LITTLE_KHZ", "1574400"))
|
||||
gpu = int(os.environ.get("PIN_GPU_HZ", "680000000"))
|
||||
# The session's profile (pin_clocks.sh writes it on the device; probes save it as profile.txt).
|
||||
prof = os.path.join(os.path.dirname(path), "profile.txt") if path else None
|
||||
if prof and os.path.exists(prof):
|
||||
kv = dict(re.findall(r"(\w+)=(\S+)", open(prof, encoding="utf-8", errors="replace").read()))
|
||||
big = int(kv.get("cpu", big)); little = int(kv.get("little", little)); gpu = int(kv.get("gpu", gpu))
|
||||
cpu, steps = {}, {}
|
||||
if not path:
|
||||
return cpu, gpu, steps
|
||||
for line in open(path, encoding="utf-8", errors="replace"):
|
||||
m = re.search(r"gpu cur=\d+ min=\d+ max=\d+ avail=([\d ]+)", line)
|
||||
if m:
|
||||
# kgsl power levels index this table from the top (level 0 = fastest).
|
||||
steps["gpu"] = sorted((int(x) for x in m.group(1).split()), reverse=True)
|
||||
for line in open(path, encoding="utf-8", errors="replace"):
|
||||
m = re.search(r"policy(\d+) cur=\d+ min=(\d+) max=(\d+) avail=([\d ]+)", line)
|
||||
if m:
|
||||
avail = sorted(int(x) for x in m.group(4).split())
|
||||
want = little if m.group(1) == "0" else big
|
||||
ok = [a for a in avail if a <= want]
|
||||
cpu[m.group(1)] = ok[-1] if ok else avail[0]
|
||||
steps[m.group(1)] = avail
|
||||
return cpu, gpu, steps
|
||||
|
||||
|
||||
def main():
|
||||
rows = parse(sys.argv[1])
|
||||
cpu_pin, gpu_pin, steps = pins(sys.argv[2] if len(sys.argv) > 2 else None)
|
||||
if not rows:
|
||||
print("NO-SAMPLES")
|
||||
sys.exit(2)
|
||||
reasons = []
|
||||
out = []
|
||||
pols = sorted({k[1:] for k in rows[0] if re.fullmatch(r"c\d+", k)}, key=int)
|
||||
for p in pols:
|
||||
cur = [int(r["c" + p].split("/")[0]) for r in rows]
|
||||
mx = [int(r["c" + p].split("/")[1]) for r in rows]
|
||||
out.append(f"c{p}={min(cur) // 1000}-{max(cur) // 1000}MHz")
|
||||
pin = cpu_pin.get(p)
|
||||
if pin:
|
||||
lower = [s for s in steps.get(p, []) if s < pin]
|
||||
floor = lower[-1] if lower else pin
|
||||
if min(cur) < floor:
|
||||
reasons.append(f"c{p} cur {min(cur) // 1000} < pin {pin // 1000}")
|
||||
if min(mx) < pin:
|
||||
reasons.append(f"c{p} max capped to {min(mx) // 1000}")
|
||||
busy = [r for r in rows if int(r.get("busy", "0") or 0) > 0]
|
||||
gpus = [int(r["gpu"]) for r in (busy or rows)]
|
||||
out.append(f"gpu={min(gpus) // 1000000}-{max(gpus) // 1000000}MHz(busy samples {len(busy)}/{len(rows)})")
|
||||
if gpu_pin and busy and min(gpus) < gpu_pin * 0.85:
|
||||
reasons.append(f"gpu {min(gpus) // 1000000} < pin {gpu_pin // 1000000}")
|
||||
tpl = max(int(r.get("tpl", 0)) for r in rows)
|
||||
thr = max(int(r.get("thr", 0)) for r in rows)
|
||||
# A devfreq max_freq write (the pin itself) shows up as kgsl's thermal_pwrlevel; only a level
|
||||
# whose frequency is below the pin is a cap.
|
||||
table = steps.get("gpu", [])
|
||||
if tpl and table and tpl < len(table):
|
||||
if gpu_pin and table[tpl] < gpu_pin:
|
||||
reasons.append(f"gpu thermal_pwrlevel {tpl} = {table[tpl] // 1000000} MHz < pin")
|
||||
elif tpl and not table:
|
||||
reasons.append(f"thermal_pwrlevel {tpl} (no OPP table to map it)")
|
||||
out.append(f"tpl={tpl} thr={thr}")
|
||||
peak = lambda k: max(int(r.get(k, 0)) for r in rows) / 1000.0
|
||||
out.append(f"peak cpu {peak('cpuT'):.1f}C gpu {peak('gpuT'):.1f}C skin {peak('skinT'):.1f}C n={len(rows)}")
|
||||
verdict = "VALID" if not reasons else "INVALID"
|
||||
print(verdict, " ".join(out), ("| " + "; ".join(reasons)) if reasons else "")
|
||||
sys.exit(0 if not reasons else 1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -51,6 +51,8 @@ wl_args() { # trace golden w h target crop
|
||||
rd12) echo "rd12 minecraft-1.21.4-rd12-odinlite-in-world.0004660351.png 854 480 4660351 0 0 0 0" ;;
|
||||
# P15: GPU-bound shaderpack scene (a single-frame trim: ssim only, not a benchmark).
|
||||
bsl) echo "bsl minecraft-1.21.4-fabric-iris-bsl-in-world.0000110725.png 854 480 110725 0 0 0 0" ;;
|
||||
# P15 S0b: FCL's MC 1.21.5 vanilla scene, a 252-frame window (benchmark + ssim on the final frame).
|
||||
fcl) echo "fcl minecraft-1.21.5-vanilla-fcl-in-world.0005998912.png 854 480 5998912 0 0 0 0" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -82,9 +84,10 @@ prep_pkg() {
|
||||
openra) tgz="$FIXTURES/openra.tgz" ;;
|
||||
rd12) tgz="$FIXTURES/minecraft-1.21.4-rd12-odinlite-in-world.tgz" ;;
|
||||
bsl) tgz="$FIXTURES/minecraft-1.21.4-fabric-iris-bsl-in-world.tgz" ;;
|
||||
fcl) tgz="${FCL_FIXTURES:-$FIXTURES}/minecraft-1.21.5-vanilla-fcl-in-world.tgz" ;;
|
||||
esac
|
||||
set -- $(wl_args $wl)
|
||||
local golden="$FIXTURES/$2"
|
||||
local golden="$FIXTURES/$2"; [ "$wl" = fcl ] && golden="${FCL_FIXTURES:-$FIXTURES}/$2"
|
||||
if [ ! -f "$tmp/$wl.trace" ]; then
|
||||
rm -rf "$tmp/x"; mkdir -p "$tmp/x"; tar xzf "$tgz" -C "$tmp/x" || exit 1
|
||||
mv "$(find "$tmp/x" -name '*.trace' | head -1)" "$tmp/$wl.trace"; rm -rf "$tmp/x"
|
||||
@@ -146,6 +149,9 @@ run_one() {
|
||||
[ "$mode" = benchmark ] && passflag="--ez benchmark true --ez benchmark_finish ${FINISH:-false} --es benchmark_result_path $app/output/benchmark.json"
|
||||
local env; env="$(arm_env "$arm")"; [ -n "$EXTRA_ENV" ] && env="${env:+$env;}$EXTRA_ENV"
|
||||
if [ "$mode" = benchmark ]; then
|
||||
# P15 validity rule: frequency/thermal sampler for the whole run (devstate.sh judges it).
|
||||
adb -s "$SER" push "$(cygpath -w "$SCRIPT_DIR/freq_sampler.sh")" /data/local/tmp/p15-freq_sampler.sh >/dev/null 2>&1
|
||||
shq "su -c 'chmod 755 /data/local/tmp/p15-freq_sampler.sh; pkill -f p15-freq_sampler.sh; rm -f /data/local/tmp/p15freq.txt; (nohup sh /data/local/tmp/p15-freq_sampler.sh /data/local/tmp/p15freq.txt 2 >/dev/null 2>&1 &)'" >/dev/null 2>&1
|
||||
shq "su -c 'nohup taskset 01 $SAMPLER $pkg 10 $app/output/benchmark.json /data/local/tmp/p14cpu.csv $TIMEOUT >/dev/null 2>&1 &'" >/dev/null 2>&1
|
||||
fi
|
||||
local am_out
|
||||
@@ -172,6 +178,10 @@ run_one() {
|
||||
sleep 1
|
||||
adb -s "$SER" exec-out "su -c 'cat /data/local/tmp/p14cpu.csv'" >"$dir/cpu.csv" 2>/dev/null
|
||||
shq "su -c 'pkill -f cpusampler'" >/dev/null 2>&1
|
||||
shq "su -c 'pkill -f p15-freq_sampler.sh'" >/dev/null 2>&1
|
||||
adb -s "$SER" exec-out "su -c 'cat /data/local/tmp/p15freq.txt'" >"$dir/freq.txt" 2>/dev/null
|
||||
SER=$SER bash "$SCRIPT_DIR/pin_clocks.sh" show >"$dir/pin.txt" 2>&1
|
||||
SER=$SER bash "$SCRIPT_DIR/devstate.sh" "$dir" trace >/dev/null 2>&1
|
||||
fi
|
||||
shq "am force-stop $pkg" >/dev/null 2>&1
|
||||
local passed="none"; [ -f "$dir/result.json" ] && passed=$(sed -n 's/.*"passed": *\([a-z]*\).*/\1/p' "$dir/result.json" | head -1)
|
||||
@@ -179,7 +189,7 @@ run_one() {
|
||||
echo "tag=$TAG wl=$wl backend=$backend arm=$arm rep=$rep mode=$mode status=$status passed=$passed dur=$(( $(date +%s) - epoch0 )) temp0=$t0 temp1=$t1" >"$dir/meta.txt"
|
||||
verify_run "$dir" "$arm" "$backend"
|
||||
local fps="-"; [ -f "$dir/benchmark.json" ] && fps=$(sed -n 's/.*"fps": *\([0-9.]*\).*/\1/p' "$dir/benchmark.json" | head -1)
|
||||
log "END $TAG $wl/$backend/$arm r$rep $mode status=$status passed=$passed fps=$fps temp=$t1 :: $(tr '\n' ' ' <"$dir/verify.txt")"
|
||||
log "END $TAG $wl/$backend/$arm r$rep $mode status=$status passed=$passed fps=$fps temp=$t1 :: $(tr '\n' ' ' <"$dir/verify.txt") $(cat "$dir/state.txt" 2>/dev/null)"
|
||||
}
|
||||
|
||||
main() {
|
||||
|
||||
@@ -8,9 +8,30 @@
|
||||
set -u
|
||||
export MSYS_NO_PATHCONV=1
|
||||
SER="${SER:-HA27Q3LQ}"
|
||||
PIN_CPU_KHZ="${PIN_CPU_KHZ:-2035200}"
|
||||
PIN_LITTLE_KHZ="${PIN_LITTLE_KHZ:-1574400}"
|
||||
PIN_GPU_HZ="${PIN_GPU_HZ:-903000000}"
|
||||
# Clock profiles (P15 measurement rules). Compare numbers only within one profile.
|
||||
# sustained (default): CPU 2035.2 MHz big/prime, 1574.4 little; GPU 680 MHz (soaked)
|
||||
# gpumax: as sustained but GPU 903 MHz (shows whether a scene is GPU-bound; not sustainable)
|
||||
# gpulow: as sustained but GPU 422 MHz (amplifies GPU cost)
|
||||
# cpulow: CPU 1286.4 big/prime, 1017.6 little; GPU 680 MHz (amplifies CPU differences)
|
||||
# cpuhunt: CPU <=1.5 GHz big/prime, <=1.25 GHz little; GPU 903 MHz - cleanly CPU-bound (CPU-overhead
|
||||
# hunting: vanilla/rd12 gap, driver-call redundancy, S1-S3). Short cool-started runs.
|
||||
# gpuhunt: CPU <=2.4 GHz big/prime, <=1.8 GHz little; GPU 578 MHz - cleanly GPU-bound (GPU-side
|
||||
# hunting: the Espryt BSL gap, pass structure, load/store).
|
||||
# PIN_* variables still override a profile's values.
|
||||
PROFILE="${PROFILE:-sustained}"
|
||||
case "$PROFILE" in
|
||||
sustained) p_cpu=2035200 p_little=1574400 p_gpu=680000000 ;;
|
||||
gpumax) p_cpu=2035200 p_little=1574400 p_gpu=903000000 ;;
|
||||
gpulow) p_cpu=2035200 p_little=1574400 p_gpu=422000000 ;;
|
||||
cpulow) p_cpu=1286400 p_little=1017600 p_gpu=680000000 ;;
|
||||
cpuhunt) p_cpu=1500000 p_little=1250000 p_gpu=903000000 ;;
|
||||
gpuhunt) p_cpu=2400000 p_little=1800000 p_gpu=578000000 ;;
|
||||
*) echo "pin_clocks.sh: unknown PROFILE $PROFILE" >&2; exit 2 ;;
|
||||
esac
|
||||
PIN_CPU_KHZ="${PIN_CPU_KHZ:-$p_cpu}"
|
||||
PIN_LITTLE_KHZ="${PIN_LITTLE_KHZ:-$p_little}"
|
||||
PIN_GPU_HZ="${PIN_GPU_HZ:-$p_gpu}"
|
||||
PROFILE_FILE=/data/local/tmp/p15-bench-profile
|
||||
KGSL=/sys/class/kgsl/kgsl-3d0/devfreq
|
||||
SAVED=/data/local/tmp/p14-clocks.saved
|
||||
|
||||
@@ -20,10 +41,12 @@ case "${1:-show}" in
|
||||
pin)
|
||||
su_sh "test -f $SAVED || { for p in /sys/devices/system/cpu/cpufreq/policy*; do echo \$p \$(cat \$p/scaling_min_freq) \$(cat \$p/scaling_max_freq); done; echo $KGSL \$(cat $KGSL/min_freq) \$(cat $KGSL/max_freq); } > $SAVED"
|
||||
su_sh "for p in /sys/devices/system/cpu/cpufreq/policy*; do want=$PIN_CPU_KHZ; [ \$p = /sys/devices/system/cpu/cpufreq/policy0 ] && want=$PIN_LITTLE_KHZ; f=0; for a in \$(cat \$p/scaling_available_frequencies); do [ \$a -le \$want ] && f=\$a; done; echo \$f > \$p/scaling_max_freq; echo \$f > \$p/scaling_min_freq; echo \$f > \$p/scaling_max_freq; done; echo $PIN_GPU_HZ > $KGSL/max_freq; echo $PIN_GPU_HZ > $KGSL/min_freq; echo $PIN_GPU_HZ > $KGSL/max_freq"
|
||||
su_sh "echo profile=$PROFILE cpu=$PIN_CPU_KHZ little=$PIN_LITTLE_KHZ gpu=$PIN_GPU_HZ > $PROFILE_FILE"
|
||||
"$0" show ;;
|
||||
restore)
|
||||
su_sh "rm -f $PROFILE_FILE"
|
||||
su_sh "test -f $SAVED && while read p mn mx; do if [ \$p = $KGSL ]; then echo \$mx > \$p/max_freq; echo \$mn > \$p/min_freq; else echo \$mx > \$p/scaling_max_freq; echo \$mn > \$p/scaling_min_freq; fi; done < $SAVED; rm -f $SAVED"
|
||||
"$0" show ;;
|
||||
show)
|
||||
su_sh "for p in /sys/devices/system/cpu/cpufreq/policy*; do echo \$p cur=\$(cat \$p/scaling_cur_freq) min=\$(cat \$p/scaling_min_freq) max=\$(cat \$p/scaling_max_freq); done; echo gpu cur=\$(cat $KGSL/cur_freq) min=\$(cat $KGSL/min_freq) max=\$(cat $KGSL/max_freq); dumpsys battery | grep temperature" ;;
|
||||
su_sh "for p in /sys/devices/system/cpu/cpufreq/policy*; do echo \$p cur=\$(cat \$p/scaling_cur_freq) min=\$(cat \$p/scaling_min_freq) max=\$(cat \$p/scaling_max_freq) avail=\$(cat \$p/scaling_available_frequencies); done; echo gpu cur=\$(cat $KGSL/cur_freq) min=\$(cat $KGSL/min_freq) max=\$(cat $KGSL/max_freq) avail=\$(cat /sys/class/kgsl/kgsl-3d0/gpu_available_frequencies); dumpsys battery | grep temperature" ;;
|
||||
esac
|
||||
|
||||
Reference in New Issue
Block a user