#!/bin/bash
# cpu_spent_by_buffers.sh - Measure CPU time spent by each page in Conkeror (web browser)
# 23.m12.2009 Daniel Clemente. v1. dcl441-bugs@yahoo.com. This code is public domain
# http://www.danielclemente.com/scripts/cpu_spent_by_buffers.sh
#
# If conkeror uses 90% CPU when you have lots of buffers open (>100), you can use this program to find out in which measure each buffer contributes to rise the CPU load. Run it to get instructions.
# More discussion hopefully on: http://article.gmane.org/gmane.comp.mozilla.conkeror/1892
#
#
# Three examples of real timings on my machine:
#
# * Good page (it doesn't choke the CPU):
# Timing 15s %CPU for URL http://en.wikipedia.org/wiki/Boeing_787
# 0.4% (average of: 0.0 0.0 1.0 0.0 0.0 0.0 5.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 )
#
# * Bad page (it consumes a bit of CPU continuously):
# Timing 15s %CPU for URL http://www.lavanguardia.es/economia/noticias/20090301/53650524375/warren-buffet-pronostica-una-economia-en-ruinas-durante-el-2009.html
# 4.12667% (average of: 17.9 8.0 1.0 2.0 1.0 2.0 16.0 2.0 3.0 2.0 1.0 2.0 2.0 1.0 1.0 )
#
# * Very broken page (it consumes lots of CPU continuously):
# Timing 15s %CPU for URL http://www.acciona.es/
# 29.0933% (average of: 33.9 40.9 24.9 29.9 24.9 26.8 38.9 26.9 25.9 30.9 25.9 23.9 27.9 26.9 27.9 )
#



AS=$(compgen -f ~/.conkeror.mozdev.org/conkeror/*.default)/sessions/auto-save
#Or set it explicitly: AS=~/.conkeror.mozdev.org/conkeror/hgwfry3w.default/sessions/auto-save
NUM_SAMPLES=15 # How many times will conkeror be timed to calculate the average CPU load. 1 second per sample
WAIT_PERIOD=10 # How many seconds to wait for before starting to time. If you use a small number, the page might not have time to load and you will time a higher CPU usage in the first seconds

function show_instructions () {
	echo "Warning: this will kill conkeror and thus save the session in the session file (probably $AS)"
	echo "Then, for each buffer which was open, conkeror will open the URL, wait for $WAIT_PERIOD seconds, and then time CPU usage for $NUM_SAMPLES seconds"
	echo "Averages will be written on screen and to file ./cpu_spent_by_buffers"
	echo
	echo "Instructions for you:"
	echo "1. Prepare in Conkeror the buffers you want to time"
	echo "2. Close other programs which may interfere in the timings"
	echo "3. Press Return when you're ready"
	read
}

function init_autosave_file () {
	pkill xulrunner-bin;
    while pidof xulrunner-bin; do echo Waiting for conkeror to die; sleep 1; done
	[ -f $AS ] || (
		if [ -f /tmp/backup-conkeror-auto-save ]; then
			echo "Using backed-up auto-save file from /tmp since $AS could not be found"
			cp /tmp/backup-conkeror-auto-save $AS
		else
			echo "Can't find auto-save file at $AS. Change AS variable in this script to the correct path."; kill $PPID
		fi
	)
}

function read_urls_to_test () {
	cat /tmp/backup-conkeror-auto-save | awk -v RS=\" '/:\/\//' 
}

function restore_autosave_file () {
	echo Restoring auto-save file;
	cp /tmp/backup-conkeror-auto-save $AS
}

function beep_start_timing () {
	beep -l 150 -f 400 -n -l 100 -f 800;
}
function beep_stop_timing () {
	beep -l 100 -f 800 -n -l 150 -f 400;
}

function boot_conkeror_with_url () {
	rm $AS &>/dev/null;
	conkeror "$url" &>/dev/null & sleep $WAIT_PERIOD;
	echo "Timing ${NUM_SAMPLES}s %CPU for URL $url";
}
function get_cpu_usages () {
	top -p `pidof xulrunner-bin` -b -n${NUM_SAMPLES} -d1 | awk '{ if($10=="%CPU") { getline; print $9 } }'
}
function compute_average () {
	(while read in; do echo $in; done) | awk '{ s += $1; all=all $1 " "; } END { print s/NR "% (average of: " all ")" }';
}


# Program starts here

show_instructions
init_autosave_file
(
read_urls_to_test | while read url; do
	boot_conkeror_with_url
	beep_start_timing
	get_cpu_usages | compute_average
	beep_stop_timing
	pkill xulrunner-bin;
done;
) | tee cpu_spent_by_each_url
restore_autosave_file



