Friday, October 30, 2015

Using trickle to control the bandwidth usage of a particular process

Recently I have written a little python script to upload my photos to flickr using the flickr api. It was fun and I will share how to do it later. However when I started uploading 600 photos to flickr at home my wife complained the Internet speed was too slow. She said she could not watch youtube and even some foreign website!

Telling her to wait is not a solution ( I could be killed :p ). So I had stop the script and wait for the 'non-busy hour' to continue. However, this way is not practical, because it's hard to define a non-busy hour. In fact, mid night might not be good as well, because sometimes I need to have a conference call. Therefore, I tried to find if any tools that can limit the traffic so that the script will not upset our life.

Finally I found trickle and it totally solves my problem.

First, we have to install trickle.

Depending on the distributions:

  • pacman -S trickle
  • apt-get install trickle
  • yum install trickle

To run a program with limited bandwidth, just run:
$ trickle -s -u UPLOAD -d DOWNWORD THE_PROGRAM

in my case:

$ trickle -s -u 40 -d 40 python flickr_upload.py

-d and -u are to specify the download and upload speed respectively. Remember the unit is KB/s while your ISP usually use kbs as the unit. You will need to convert it in order to set a reasonable throughput for the process. You can check with this online conversion calculator

If you have a set of programs run by an user you can limit them buy running a trickled. For example:
$ trickled -u 40 -d 40
$

Then you can limit any program run by this user with this limit setting:
$ trickle program1

$ trickle program2
$ # more...

After limited the upload and download speed of my python script, everybody is satisfied. Though it takes much longer to upload photos to flickr, it's okay for me and my wife can browse and watch whatever she wants. Happy ending...

PS: 
Please note that trickle cannot resolve all cases. It only works when the application (the binary) is using the dynamic library glibc. To check if it is using the glibc, you can use the following command

$ ldd /usr/bin/python |grep libc
libc.so.6 => /usr/lib/libc.so.6 (0x00007f96a991f000)

If it is not using glibc, then you have find another way, probably using iptable or enable QoS on the router if it is supported

Ref:

  1. https://wiki.archlinux.org/index.php/Trickle
  2. http://linux.die.net/man/1/trickle