Sunday, October 18, 2015

Inside my video player ASUS HDP-R1 - CPU usage without top

For several years I've been using ASUS HDP-R1 video player for my media files. Recently I've had samoe problems playing big mkv file. I decided to dig into the player to see what's inside and check the CPU usage while playing movies.

We can telnet to the player:

Venus login: root
warning: cannot change to home directory


BusyBox v1.1.3 (2011.05.25-05:45+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

/ #


uname -a gives us:

/ # uname -a
Linux Venus 2.6.12.6-VENUS #323634 Wed May 25 13:40:36 CST 2011 mips unknown


And let's check the CPU:

/ # cat /proc/cpuinfo
system type             : Realtek Venus
processor               : 0
cpu model               : MIPS 24K V7.8
BogoMIPS                : 269.51
wait instruction        : yes
microsecond timers      : yes
tlb_entries             : 32
extra interrupt vector  : yes
hardware watchpoint     : yes
ASEs implemented        : mips16
VCED exceptions         : not available
VCEI exceptions         : not available


I just wanted to check CPU usage however neither top nor mpstat commands are available.
My first plan was to compile top binary from sources linking it staticly but it's not x86 architecture so I had no other hardware to do that. Of cource as you suppose there are no compilers available in this box.
I came up with the following solution - read cpu usage directly from the /proc filesystem with /bin/sh.

Let's try:

/ # cat /proc/stat
cpu  4916 3748 25087 1879421 2633 326 459 0
cpu0 4916 3748 25087 1879421 2633 326 459 0
intr 2046721 0 0 86168 40259 0 3704 1916590 0
ctxt 10942464
btime 1388589011
processes 6008
procs_running 3
procs_blocked 0


We are interested in the first line giving us the summary cpu usage of all the cores (in this case only cpu0). The magic numbers are:
  • user: normal processes executing in user mode
  • nice: niced processes executing in user mode
  • system: processes executing in kernel mode
  • idle: twiddling thumbs
  • iowait: waiting for I/O to complete
  • irq: servicing interrupts
  • softirq: servicing softirqs
These values change over the time. To measure cpu usage we must take the user,system and idle values at one moment and again in let's say 2 seconds. So we have:

Now:

current_user
current_system
current_idle

in 2 seconds (current values become the previous ones):

prev_user = current_user
prev_system = current_system
prev_idle = current_idle

Now we can calculate the cpu usage with this formula:

current_total = current_user + current_system + current_idle
prev_total = prev_user + prev_system + prev_idle

diff_total =  current_total - prev_total
diff_idle = current_idle - prev_idle

 cpu_usage (%) = (diff_total - diff_idle)/diff_total*100

Now we can write the shell script to calculate every 2 seconds:

#!/bin/sh
p_user=0
p_system=0
p_idle=0
p_total=0

while true; do


#current


l=$(cat /proc/stat | grep "cpu ")
c_user=$(echo $l | cut -f2 -d' ')
c_nice=$(echo $l | cut -f3 -d' ')
c_system=$(echo $l | cut -f4 -d' ')
c_idle=$(echo $l | cut -f5 -d' ')
#calc
c_total=$(($c_idle+$c_user+$c_system))
d_total=$(($c_total-$p_total))
d_idle=$(($p_idle-$p_idle))
totalminusidle=$(($d_total-$d_idle))
#cpu=$((($totalminusidle/$d_total)*100))
echo -n $totalminusidle
echo -n "#"
echo -n $d_total
echo
sleep 2


#prev


p_user=$c_user
p_nice=$c_nice
Psystem=$c_system
p_idle=$c_idle
p_total=$c_total

done


We save it in writable /tmp space as top.sh. It will be there until device reboot.

It's not the perfect script. I can't use bash feaures here as  I don't have one. We have a little problem here. The cpu usage will be totally inaccurate because the shell doesn't support floating point arithmetic. And on this machine I don't have any tools to do that (like bc, dc). There is awk but it always returns nan, trying to do some math operations:

/ # awk 'BEGIN{print 2+2}'
nan


So the only not ellegant idea I came up with was to list the values used in the final CPU equation and then do the calculations somewhere else, in spreadsheet  for example :).  (yes it's not realtime). So when we run the script we got: (we omit the first row as we didn't have the prev values yet):


/tmp # sh ./top.sh

31401#2110151
33#232
34#233
29#228
31#232
34#233
33#232
32#231
31#232
33#232
33#232
32#231
29#230

Feeding spreadsheet with them we have:

                  a                  b                            a/b*100
33 232
14,224137931
34 233
14,5922746781
29 228
12,7192982456
31 232
13,3620689655
34 233
14,5922746781
33 232
14,224137931
32 231
13,8528138528
31 232
13,3620689655
33 232
14,224137931
33 232
14,224137931
32 231
13,8528138528
29 230
12,6086956522

When the player is just turned on and idle the cpu usage is about 12-14%
While playing mkv hd movie (720p) the cpu usage is about 20%
While playing mkv full hd movie (1080p) the cpu usage is about 25%

 That's all for now

No comments:

Post a Comment