tech talk #5 – internet browsers & cgroups

when i began to work with linux and related os’es, primary and secondary memories (ram and disk space, respectively) were high priced as well as scarce resources. it looks like an era has passed, when i think about my bigfoot 10 gb hdd mounted in the 5¼” slot of my desktop. another interesting thing to notice: programmers were also more concerned about memory and disk utilization.

then, the flash drives came, technology improved the storage capabilities and the prices went down the floor. lovey, BUT… this brought an undesired side-effect: the laziness and sloppiness of the programmers regarding memory usage and disk space. my point: just because it’s cheap, it doesn’t mean you no longer need to care about how your program deals with the system memory. (and no, it’s not an operating system issue, but a poorly designed piece of software running on top of it that’s to be blamed.)

if you are a linux and a firefox user, you are very familiar with ff’s disgraceful behavior: the browser’s long known memory leak issue and faulty memory management. recently they’ve redesigned the program, that now spans tons of threads that end up sucking all the resources of your machine, leaving you no option but the “PoPo procedure”: power off, power on. web content and privileged content are memory greedy tasks (threads) that eat all the physical and virtual memory of your computer, and if you don’t have an OOM killer set, you’re doomed.

with this in mind i decided to take a look on the cgroups subject. it’s a means of controlling how programs use your machine resources. my primary focus here is memory, but you can control cpu time and disk io, if you will.

so… below you will find a nice script i wrote. at this moment i’m running it against chrome (which is another piece of sh!t, along with opera, which is also another piece of sh!t – to be honest, all browsers are sh!te. period. but i tend to like firefucks better), just because i’m struggling to find suitable memory and swap values that don’t cause linux to trigger the OOM for firefox – the operating system takes a bit longer before deciding to oom_kill chrome (maybe chrome handles memory slightly better than ff). dunno about opera, because despite being neat and having some interesting features (like the built-in “player” and other eye candies), it rendered itself useless, as it still presents a bug that makes the browser incapable of playing spotifail songs in the web version of the platform – IIRC, it happens with deezer too).

about the script… first things first: you will need root access to create a new entry in the /sys/fs/cgroup.

# cgcreate -t luser:luser-group -a luser:luser-group -g memory:browsers

luser refers to the user who’s gonna make use of cgroups, and luser-group is the group this luser belongs to. the “-t” switch gives the luser access to the tasks file, and the “-a” gives the luser RW access to the newly created entry. browsers is the entry created in /sys/fs/cgroup/memory directory.

and now the script:

#!/bin/bash

# to be used later - OOM score adjustment
pid=

# browser chosen - retrieved from getopts
nav=

# 1 GB in bytes
gig=$(echo 2 30 ^ p | dc)

# memory limit
mem=$(echo $gig 2 \* $gig 2 / + p | dc)

# ram + swap ($gig + $mem)
memsw=$(echo $mem $gig + p | dc)

# warning limit
soft=$(echo $mem $gig 2 / - p | dc)

usage()
{
  cat << eom
$(basename $0) [ -f | -c | -o | -h ]

-f ::= firefucks
-c ::= chromergh
-o ::= poorly sung opera
-h ::= this message
eom
}

if [[ $# -ne 1 ]]; then
  usage
  exit
fi

# adjusting memory limits
cgset -r memory.limit_in_bytes=$mem -r \ memory.memsw.limit_in_bytes=$memsw \
-r memory.soft_limit_in_bytes=$soft browsers

while getopts ":fcoh" opt; do
  case $opt in
    f)
      cgexec -g memory:browsers firefox > ~/tmp/ff.out 2>&1 &
      sleep 80
      nav=$opt
      pid=$(pidof firefox);;
    c)
      cgexec -g memory:browsers chrome > ~/tmp/ff.out 2>&1 &
      sleep 80
      nav=$opt
      pid=$(pidof chrome | sed 's/ /\n/g' | sort | head -1);;
    o)
      cgexec -g memory:browsers opera > ~/tmp/ff.out 2>&1 &
      sleep 80
      nav=$opt
      pid=$(pidof chrome | sed 's/ /\n/g' | sort | head -1);;
    h)
      usage;;
  esac
done

cd /proc/$pid
echo +650 > oom_score_adj
cd $HOME

case $nav in
  f)
    echo $(pidof firefox) $(pidof firefox-bin) $(pidof plugin-container) | \
    sed 's/ /\n/g' | sort | \
    while read i; do
      echo $i >> /sys/fs/cgroup/memory/browsers/cgroup.procs
    done;;
  c)
    echo $(pidof chrome) | sed 's/ /\n/g' | sort | \
    while read i; do
      echo $i >> /sys/fs/cgroup/memory/browsers/cgroup.procs
    done;;
  o)
    echo $(pidof chrome) | sed 's/ /\n/g' | sort | \
    while read i; do
      echo $i >> /sys/fs/cgroup/memory/browsers/cgroup.procs
    done;;
esac

exit $?

that’s it for today. hope that helps. =)

About rennrad

It's all about two wheels, being them bicycles or motorcycles.
This entry was posted in debian, linux, tech and tagged , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s