==========BEGIN NOTES========== - First script "runme" was executed in the terminal - Second script "benchmark.sh" was called by "runme" with various parameters - "runme" was run four times in total, once for each benchmark condition, with the benchmark name changed as appropriate - Scripts below are functionally identical to scripts that were run including timestamp issue, but commented code was removed, a deprecated flag related to 7zip was removed, and one string was corrected in FFmpeg results file - Only data from the very first "2 P cores + 4 E cores" benchmarks has been analyzed so far - FFmpeg version N-123623-g238df21a4f was used - Macmon v0.7.0 was used ==========END NOTES========== ==========BEGIN SCRIPT "RUNME"========== #! /bin/zsh echo "2 P cores + 4 E cores" # all cores ./benchmark.sh -c 120 -d 5 -n nameOfBenchmark2P4E -t 6 echo "0 P cores + 4 E cores" # all E cores ./benchmark.sh -c 120 -d 5 -n nameOfBenchmark0P4E -t 0 -p 0 echo "2 P cores + 0 E cores" # all P cores ./benchmark.sh -c 120 -d 5 -n nameOfBenchmark2P0E -t 2 echo "0 P cores + 2 E cores" ./benchmark.sh -c 120 -d 5 -n nameOfBenchmark0P2E -t 0 -p 0 echo "1 P core + 0 E cores" ./benchmark.sh -c 120 -d 5 -n nameOfBenchmark1P0E -t 1 echo "0 P cores + 1 E core" ./benchmark.sh -c 120 -d 5 -n nameOfBenchmark0P1E -t 1 -p 0 echo "done!" ==========END SCRIPT "RUNME"========== ==========BEGIN SCRIPT "BENCHMARK.SH"========== #! /bin/zsh echo starttime=$(date "+%Y-%m-%dT%H-%M-%S") crf=18 # Supposed to be visually lossless # SET DEFAULT VALUES FOR OPTIONS cooldowntime=5 duration=2 sampleinterval=500 foldername=$(echo $starttime) pcoreusage=1 threads=$(sysctl -n hw.ncpu) video="ffmpeg.mkv" # INTERPRET OPTIONS AND FLAGS, PRINT HELP TEXT while getopts ":c:d:hi:n:p:t:v:" option; do case $option in c) # set cooldown time in seconds if [[ $OPTARG =~ ^-?[0-9]+$ ]]; then cooldowntime=$OPTARG else echo "Error: invalid argument for '-c' option. Must be integer" echo exit fi;; d) # set number of test cycles if [[ $OPTARG =~ ^-?[0-9]+$ ]]; then duration=$OPTARG else echo "Error: invalid argument for '-d' option. Must be integer" echo exit fi;; h) # help echo "Parameters to tune benchmark script." echo echo "Syntax: ./runme.sh [-c|d|h|i|n|p|t|v|z]" echo echo "Options:" echo "c: time to continue logging system monitors during cooldown period" echo " (seconds, default = 5)" echo "d: duration of test" echo " (number of cycles, default = 2)" echo "h: print this text and exit" echo "i: configure the sample rate of macmon" echo " (milliseconds per sample, default = 500)" echo "n: name of folder in logs/, output/, and results/" echo " (string, default = benchmark start time)" echo "p: use performance cores" echo " (0 = false, 1 = true, default = 1)" echo " Note: it is NOT possible to disable usage of efficiency cores" echo "t: number of threads" echo " (default = all logical processors)" echo " Note: number of threads is NOT reduced automatically using '-p 0'" echo " User must manually input number of E cores in system" echo " Hint: use 'sysctl hw | grep perflevel1.logicalcpu' if not known" echo "v: video file to compress in input/" echo " (default = input/ffmpeg.mkv" echo exit;; i) # set time between system monitor samples in ms if [[ $OPTARG =~ ^-?[0-9]+$ ]]; then sampleinterval=$OPTARG else echo "Error: invalid argument for '-i' option. Must be integer" echo exit fi;; n) # choose name for logs, output, and results folders foldername=$OPTARG;; p) # choose between all cores or E cores only on Apple silicon if [[ $OPTARG -eq 0 || $OPTARG -eq 1 ]]; then pcoreusage=$OPTARG else echo "Error: invalid argument for '-p' option. Must be 0 or 1" echo exit fi;; t) # set number of threads to use if [[ $OPTARG =~ ^-?[0-9]+$ ]]; then threads=$OPTARG else echo "Error: invalid argument for '-t' option. Must be integer" echo exit fi;; v) # video file for ffmpeg video=$OPTARG;; \?) # invalid option echo "Error: Invalid option" echo "-h for help" echo exit;; esac done # PRINT OPTIONS TO TERMINAL echo "Running $duration test cycles on $threads threads" if [[ $pcoreusage -eq 0 ]]; then echo "Only efficiency cores will be used" elif [[ $pcoreusage -eq 1 ]]; then echo "All cores may be used" fi echo "Transcoding video input/$video" echo "Saving system monitor output every $sampleinterval milliseconds" echo "Continuing to log for $cooldowntime seconds after benchmark ends" echo "Check results/$foldername for results" echo # CONTROL+C KILLS CHILD PROCESSES TOO cleanup() { # WARNING: I forgot if this function actually works correctly echo "exiting" kill -KILL -- -$$ 2>/dev/null exit } trap cleanup SIGINT SIGTERM # CREATE FOLDERS AND FILES FOR OUTPUTS mkdir logs/$foldername mkdir output/$foldername mkdir results/$foldername touch logs/$foldername/output-timestamps.log echo "benchmark was started at: $starttime" >> logs/$foldername/output-timestamps.log # BEGIN LOGGING SYSTEM MONITORS macmon pipe -i $sampleinterval > logs/$foldername/macmon-json.log & macmon_pid=$! echo "Gathering baseline logs for 5 seconds before beginning." sleep 5s # BENCHMARK LOOP { # SETUP for ((i = 0; i < $duration; i++)); do cyclecounter=$((i + 1)) echo "begin test cycle $cyclecounter of $duration" echo "ffmpeg..." echo touch logs/$foldername/ffmpeg$cyclecounter.log echo "ffmpeg $cyclecounter start: $(date "+%Y-%m-%dT%H-%M-%S")" >> logs/$foldername/output-timestamps.log ffmpeg -i input/$video -threads $threads -c:v libx264 -preset slow -crf $crf -c:a copy -progress pipe:3 output/$foldername/ffmpeg$cyclecounter.mp4 3> logs/$foldername/ffmpeg$cyclecounter.log & current_pid=$! if [[ $pcoreusage -eq 0 ]]; then taskpolicy -b -p $current_pid; fi wait echo "ffmpeg $cyclecounter end: $(date "+%Y-%m-%dT%H-%M-%S")" >> logs/$foldername/output-timestamps.log echo echo "ffmpeg done!" echo done # CONTINUE LOGGING WHILE SYSTEM COOLS, THEN STOP LOGGING echo "Benchmark done. Begin cooldown period of $cooldowntime seconds." sleep $cooldowntime kill "$macmon_pid" } & wait echo "Cooldown done. Processing data..." # PROCESS MACMON DATA touch results/$foldername/macmon-formatted.log echo "timestamp (iso 8601), cpu power, all power, system power, average cpu temperature, ram usage, total ram, swap usage, total swap, pcpu usage, ecpu usage" >> results/$foldername/macmon-formatted.log jq '[.timestamp, .cpu_power, .all_power, .sys_power, .temp.cpu_temp_avg, .memory.ram_usage, .memory.ram_total, .memory.swap_usage, .memory.swap_total, .pcpu_usage[0], .ecpu_usage[0]] | @csv' logs/$foldername/macmon-json.log >> results/$foldername/macmon-formatted.log # PROCESS FFMPEG DATA touch results/$foldername/ffmpeg-formatted.log for ((i = 0; i < $duration; i++)); do cyclecounter=$((i + 1)) echo "time (microseconds from start of video file), frame number, fps, total size (bytes), bitrate (kbit/s)" >> results/$foldername/ffmpeg-formatted.log # CONVERT LOG FILES INTO CSV FILES (WOW THIS SUCKS) ffmpeglinecount=$(cat logs/$foldername/ffmpeg$cyclecounter.log | grep frame= | wc -l) for ((j = 0; j < $ffmpeglinecount; j++)); do ffmpegwhichline=$((j + 1)) ffmpegtime=$(cat logs/$foldername/ffmpeg$cyclecounter.log | grep out_time_us= | head -n $ffmpegwhichline | tail -n 1 | cut -c 13-100) ffmpegframenumber=$(cat logs/$foldername/ffmpeg$cyclecounter.log | grep frame= | head -n $ffmpegwhichline | tail -n 1 | cut -c 7-100) ffmpegfps=$(cat logs/$foldername/ffmpeg$cyclecounter.log | grep fps= | head -n $ffmpegwhichline | tail -n 1 | cut -c 5-100) ffmpegtotalsize=$(cat logs/$foldername/ffmpeg$cyclecounter.log | grep total_size= | head -n $ffmpegwhichline | tail -n 1 | cut -c 12-100) ffmpegbitrate=$(cat logs/$foldername/ffmpeg$cyclecounter.log | grep bitrate= | head -n $ffmpegwhichline | tail -n 1 | cut -c 9-14) echo "$ffmpegtime,$ffmpegframenumber,$ffmpegfps,$ffmpegtotalsize,$ffmpegbitrate" >> results/$foldername/ffmpeg-formatted.log done done # GRAB FILE TIMESTAMPS touch results/$foldername/file-sizes-timestamps.log echo "name, timestamp (start), timestamp (end)" >> results/$foldername/file-sizes-timestamps.log for ((i = 0; i < $duration; i++)); do cyclecounter=$((i + 1)) thisffmpegtimestart=$(stat -f '%Fc' logs/$foldername/ffmpeg$cyclecounter.log) thisffmpegtimeend=$(stat -f '%Fa' logs/$foldername/ffmpeg$cyclecounter.log) echo "ffmpeg$cyclecounter.log, $thisffmpegtimestart, $thisffmpegtimeend" >> results/$foldername/file-sizes-timestamps.log thisffmpegtimestart=$(stat -f '%Fc' output/$foldername/ffmpeg$cyclecounter.mp4) thisffmpegtimeend=$(stat -f '%Fa' output/$foldername/ffmpeg$cyclecounter.mp4) echo "ffmpeg$cyclecounter.mp4, $thisffmpegtimestart, $thisffmpegtimeend" >> results/$foldername/file-sizes-timestamps.log done echo "Done processing! Check results/ for benchmark data." ==========END SCRIPT "BENCHMARK.SH"==========