Howto: adjust dynamically upload rate and other attributes to favor one special group of torrents in rtorrent

Skip to first unread message

Krisztian Kovacs

Jun 10, 2015, 11:16:55 AM6/10/15
It's not rtorrent-ps specific but I couldn't find anything about this on the net, so here's my scenario and solution for it, maybe it will be good for others as well.

Actually, the idea of dynamically adjusting the upload rate came from you, pyroscope :)

Scenario: all we want to do is seeding (unfortunately we have to download before it :) ). We want to distinguished between 2 groups: a special group and the rest of them.
- special group: torrents that belong to sites where seeding back is pretty hard. So we want to favor this group in any way.
- the rest: seeding back is pretty easy, so it's not so important to provide the best circumstances for them, but we still want to seed as many of them as we can.

Realization only in the rtorrent config:
- we use multiple watch directories to specify which belongs to the special group with the help of 'd.custom2=1' attribute (you can use more than 2, of course)
- we raise the default min_peers, max_peers and max_uploads values for the special group.
- we define a throttle group (named 'slowup') and set an inital value for it. The special group doesn't use it, the rest of the torrents will use this 'slowup' throttle forever.
- we want to adjust the upload rate of this 'slowup' throttle on the fly depending on the special group current upload rate
- you can check the current up rate values using ^X and 'i='

Here is the relevant (and truncated) part of the '.rtorrent.rc' (I left the defaults at the beginning to see what values I have). You have to modify the following values in it to meet your needs (see the explanation in the commnets):
- at 'd.modify_slots_custom2'
- at 'd.modify_slots_others'
- at the beginning of 'get_new_uprate_limit' : 'sluplimit' , 'sldownlimit'

##### begin: Default connection settings #####

# Global upload and download rate in KiB (download_rate, upload_rate). "0" for unlimited.
.global_down.max_rate.set_kb = 8000
.global_up.max_rate.set_kb   = 1900

# Maximum and minimum number of peers to connect to per torrent while downloading (applies to the 'slowup' throttle group). (min_peers, max_peers)
.min_peers.normal.set = 89
.max_peers.normal.set = 100

# Same as above but for seeding completed torrents (-1 = same as downloading) (seeds per torrent) (applies to the 'slowup' throttle group). (min_peers_seed, max_peers_seed)
.min_peers.seed.set = 29
.max_peers.seed.set = 50

# Maximum number of simultanious uploads per torrent. (upload slots!) (applies to the 'slowup' throttle group). (max_uploads)
.max_uploads.set   = 15

# Maximum number of simultaneous downloads and uploads slots (global slots!) (max_downloads_global, max_uploads_global)
throttle = 300
throttle   = 300

# Throttles rates for (groups of) downloads or IP ranges. (throttle_up) These throttles borrow bandwidth from the global throttle and thus are limited by it too.
# You can assign throttles to a stopped download with Ctrl-T. The NULL throttle is a special unlimited throttle that bypasses the global throttle.
# Limits the upload rate to 600 kb/s for the slowup throttle group..
.up = slowup,600

##### begin: Directory settings #####

# Watch directories for new torrents (metafiles).
= watch_dir_1,5,10,"load.start=/mnt/Torrents/.rtorrent/.queue/safe/*.torrent,d.custom2.set=1"
= watch_dir_3,5,10,"load.start=/mnt/Torrents/.rtorrent/.queue/unsafe/*.torrent,d.throttle_name.set=slowup"

##### begin: Favoring special group #####

# Method to modify the min_peers_seed, max_peers_seed, max_uploads values of custom2 torrents for both downloading and uploading
.insert  = d.modify_slots_custom2,simple,"d.peers_min.set=99;d.peers_max.set=100;d.uploads_max.set=50"
# Method to modify the other group values as well when a hashcheck is finished
.insert  = d.modify_slots_others,simple,"d.peers_min.set=29;d.peers_max.set=50;d.uploads_max.set=15"
# Modify only the special group values when a new torrent is added for downloading
.set_key =,modify_slots_custom2,"branch={d.custom2=,d.modify_slots_custom2=}"
.insert  = d.modify_slots_both,simple,"branch={d.custom2=,d.modify_slots_custom2=,d.modify_slots_others=}"
# Modify both group values when torrent is added for hashchecking or rtorrent is restarted
.set_key =,modify_slots_hashchecked_both,"branch=d.complete=,d.modify_slots_both=}"

# Dynamically adjusts the 2nd group (slowup throttle) uprate (upload speed) to always leave enough bandwidth to the 1st main group.
#   It works like this: checks the current throttle uprate and main uprate (with the help of the global uprate), then it raise or reduce the throttle limit according to the uprate of the main group.
#   You should leave a considerable amount of gap between the top of the cap (sluplimit , e.g. 1400) and the global upload rate (upload_rate : the global upload limit , e.g. 1900) to be able to work efficiently (to leave bandwidth to the main group between checks (within that 20 seconds interval)).
# Gets the new uprate limit for slowup throttle. You have to specify the top of the cap (sluplimit : highest allowable cap in KiB, e.g. 1440) and the bottom of the cap (sldownlimit : lowest allowable cap in KiB, e.g. 100).
.insert = get_new_uprate_limit,value|simple,"execute.capture=bash,-c,\"sluplimit=1400;sldownlimit=100;allup=\$\{1%.*\};slowup=\$\{2%.*\};let mainup=\$\{allup// /\}-\$\{slowup// /\};if [ \\\"\$mainup\\\" -lt 0 ]; then mainup=0;fi;let newslowup=\$sluplimit-\$mainup;if [ \\\"\$newslowup\\\" -gt \\\"\$sluplimit\\\" ];then echo \$sluplimit;elif [ \\\"\$newslowup\\\" -gt \\\"\$sldownlimit\\\" ];then echo \$newslowup;else echo \$sldownlimit;fi\",getNewUprateLimit,$convert.kb=$throttle.global_up.rate=,$convert.kb=$throttle.up.rate=slowup"
# Sets the new uprate limit to slowup throttle
.insert = assign_new_uprate_limit,simple,"throttle.up=slowup,$get_new_uprate_limit="
# Let it run in every 20 seconds
= adjust_throttle_slowup,14,20,"assign_new_uprate_limit="

# Helper method to display the current rate information: after CTRL+x , you can use: i= . It displays: MainUpRate: 1440 , ThrottleUpRate: 92 , ThrottleLimit: 100
.insert = get_rates_info,value|simple,"execute.capture=bash,-c,\"allup1=\$\{1%.*\};slowup2=\$\{2%.*\};slowlimit1=\$\{3%.*\};let mainup1=\$\{allup1// /\}-\$\{slowup2// /\};echo \\\"MainUpRate: \$mainup1 , ThrottleUpRate: \$\{slowup2// /\} , ThrottleLimit: \$\{slowlimit1// /\}\\\"\",getRatesInfo,$convert.kb=$throttle.global_up.rate=,$convert.kb=$throttle.up.rate=slowup,$convert.kb=$throttle.up.max=slowup"
.insert = i,simple,"print=$get_rates_info="

The logic inside the 'get_new_uprate_limit' method is this (I could have put it in a separate file e.g. called , but I don't know how rtorrent handles/caches the external files, and we want to trigger it pretty frequently.):

=1400;sldownlimit=100;allup=${1%.*};slowup=${2%.*};let mainup=${allup// /}-${slowup// /};
if [ "$mainup" -lt 0 ]; then    mainup=0;fi;
let newslowup
=${sluplimit// /}-${mainup// /};
if [ "$newslowup" -gt "$sluplimit" ]; then    echo $sluplimit;elif [ "$newslowup" -gt "$sldownlimit" ]; then    echo $newslowup;else    echo $sldownlimit;fi

Note: I have to admit that I don't really know anything about bittorrent protocol, so I don't know how connected clients behaves upon that possibly frequent speed change. The above values are only based on pure experience. If you have any idea about this don't hesitate to share it. :)


Krisztian Kovacs

Jun 18, 2015, 6:44:31 AM6/18/15
I have missed out 1 thing: increasing priority to high for the special group (which only used during downloading, I think).
So the correct watch directory definitions are:

# Watch directories for new torrents (metafiles).

= watch_dir_1,5,10,"load.start=/mnt/Torrents/.rtorrent/.queue/safe/*.torrent,d.custom2.set=1,d.priority.set=3"
= watch_dir_3,5,10,"load.start=/mnt/Torrents/.rtorrent/.queue/unsafe/*.torrent,d.throttle_name.set=slowup"
Reply all
Reply to author
0 new messages