My Internet connection slows down when I download -- how can I speed it up?
You're browsing the Web. It's smooth, fast sailing, with pages loading in a snap. Then you start a download -- and what was formerly a fast Internet connection turns into a slower-than-dialup experience. What happened?
Why Web browsing slows down when downloading files
Believe it or not, this is common. If you're like me, you have a fast fiber, DSL or cable modem hookup to the Internet, directly hooked to your computer. You're probably using file sharing applications all the time, as well. This causes terrible Web browsing -- and you can easily figure that out, because as soon as you stop any file sharing applications, Web browsing speed returns back to normal.
The slowdown is caused by the queues at your ISP (or your modem). The ISP limits your Internet speed either at the modem, or at the router assigned to your modem. Since information can't come in as fast as possible, long queues of pending information build up in your router/modem.
The effect? After you click on a link in your Web browser, quite a lot of information (usually, your download) needs to be dispatched before you get to see the new Web page.
The solution: rate-limiting (odd, isn't it?)
Counterintuitive as it may sound, the solution to the queues is to limit the rate at which information reaches your computer, directly on your computer. By using a clever combination of bandwidth limiting and priorization of outbound packages, you can have almost-normal Web browsing speeds, combined with fast downloads.
In other words:
- Anything your computer sends to the Internet will be given priorities, and important information will jump the queue. Sends of acknowledgements and interactive traffic (remote desktops, shells) will get priority.
- If any computer attempts to send data to your computer too quickly, your computer will tell it to slow down. This will avoid the buildup in the queue at your ISP.
Basically, you'll be executing a tradeoff: decreasing latency at the expense of a bit (5% to 10%) of bandwidth, but the cost is certainly worth it.
Now, you may balk because this technique requires you to actually scale back (a bit) your connection speed. Do not -- if you follow through, your effective download speed will go up, because TCP acknowledgements arrive to their destination faster. If you're using BitTorrent (which requires uploading), you'll see a stable, maxed-out, download speed, instead of seeing dips in download speed when uploading.
As usual, the solution is a clever script that does everything for you, instead of you having to do it manually.
The script that solves the speed problem
Further below, you'll find instructions on how to use it.
#!/bin/bash # Wonder Shaper # please read the README before filling out these values # # Set the following values to somewhat less than your actual download # and uplink speed. In kilobits. Also set the device that is to be shaped. DOWNLINK=176 UPLINK=120 DEV=eth1 # low priority source netmasks NOPRIOHOSTSRC= # low priority destination netmasks NOPRIOHOSTDST= # low priority source ports NOPRIOPORTSRC="6881 6882 13810 6346 4800" # low priority destination ports NOPRIOPORTDST= # high priority source netmasks HIPRIOHOSTSRC= # high priority destination netmasks HIPRIOHOSTDST= # high priority source ports HIPRIOPORTSRC="5900 5901" # high priority destination ports HIPRIOPORTDST= if [ "$1" = "status" ] then echo "Queueing disciplines:" tc -s qdisc ls dev $DEV rootclassoutput=`tc -s class ls dev $DEV | grep -A 5 "htb 1:1 "` allclassesoutput=`tc -s class ls dev $DEV` echo "" echo "Root class:" echo "$rootclassoutput" echo "" echo "Child classes:" echo "$allclassesoutput" | cut -d " " -f 6,7,8,9,10,11 --complement exit fi # clean existing down- and uplink qdiscs, hide errors tc qdisc del dev $DEV root 2> /dev/null > /dev/null tc qdisc del dev $DEV ingress 2> /dev/null > /dev/null if [ "$1" = "stop" ] then exit fi ###### uplink # we'll have four classes: # 10: acknowledgements and traffic marked as interactive (Minimize-Delay) # 20: high-priority outbound traffic # 30: regular traffic # 40: low-priority outbound traffic and traffic marked as bulk (Maximize-Throughput) # install root HTB, point default traffic to 1:30: tc qdisc add dev $DEV root handle 1: htb default 30 # shape everything at $UPLINK speed - prevents huge outbound queues: tc class add dev $DEV parent 1: classid 1:1 htb rate ${UPLINK}kbit burst 5k tc class add dev $DEV parent 1:1 classid 1:10 htb rate ${UPLINK}kbit ceil ${UPLINK}kbit burst 5k prio 1 tc class add dev $DEV parent 1:1 classid 1:20 htb rate ${UPLINK}kbit ceil ${UPLINK}kbit burst 5k prio 2 tc class add dev $DEV parent 1:1 classid 1:30 htb rate $[8*$UPLINK/10]kbit ceil ${UPLINK}kbit burst 5k prio 3 tc class add dev $DEV parent 1:1 classid 1:40 htb rate $[6*$UPLINK/10]kbit ceil ${UPLINK}kbit burst 5k prio 4 # all get Stochastic Fairness: tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10 tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10 tc qdisc add dev $DEV parent 1:30 handle 30: sfq perturb 10 tc qdisc add dev $DEV parent 1:40 handle 40: sfq perturb 10 # TOS Minimum Delay (ssh, NOT scp) in 1:10: tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip tos 0x10 0xff \ flowid 1:10 # To speed up downloads while an upload is going on, put ACK packets in 1:10: tc filter add dev $DEV parent 1:0 protocol ip prio 11 u32 \ match ip protocol 6 0xff \ match u8 0x05 0x0f at 0 \ match u16 0x0000 0xffc0 at 2 \ match u8 0x10 0xff at 33 \ flowid 1:10 # High-priority traffic in 1:20: for a in $HIPRIOPORTDST ; do tc filter add dev $DEV parent 1: protocol ip prio 12 u32 match ip dport $a 0xffff flowid 1:20 done for a in $HIPRIOPORTSRC ; do tc filter add dev $DEV parent 1: protocol ip prio 12 u32 match ip sport $a 0xffff flowid 1:20 done for a in $HIPRIOHOSTSRC ; do tc filter add dev $DEV parent 1: protocol ip prio 12 u32 match ip src $a flowid 1:20 done for a in $HIPRIOHOSTDST ; do tc filter add dev $DEV parent 1: protocol ip prio 12 u32 match ip dst $a flowid 1:20 done # Low-priority traffic in 1:40: for a in $NOPRIOPORTDST ; do tc filter add dev $DEV parent 1: protocol ip prio 13 u32 match ip dport $a 0xffff flowid 1:40 done for a in $NOPRIOPORTSRC ; do tc filter add dev $DEV parent 1: protocol ip prio 13 u32 match ip sport $a 0xffff flowid 1:40 done for a in $NOPRIOHOSTSRC ; do tc filter add dev $DEV parent 1: protocol ip prio 13 u32 match ip src $a flowid 1:40 done for a in $NOPRIOHOSTDST ; do tc filter add dev $DEV parent 1: protocol ip prio 13 u32 match ip dst $a flowid 1:40 done # Maximize throughput (scp, BitTorrent, uploads) in 1:40: tc filter add dev $DEV parent 1:0 protocol ip prio 14 u32 \ match ip tos 0x08 0xff \ flowid 1:40 # rest is 'non-interactive' ie 'bulk' and ends up in 1:30 tc filter add dev $DEV parent 1: protocol ip prio 15 u32 \ match ip dst 0.0.0.0/0 \ flowid 1:30 ########## downlink ############# # slow downloads down to somewhat less than the real speed to prevent # queuing at our ISP. Tune to see how high you can set it. # ISPs tend to have *huge* queues to make sure big downloads are fast # # attach ingress policer: tc qdisc add dev $DEV handle ffff: ingress # filter *everything* to it (0.0.0.0/0), drop everything that's # coming in too fast: tc filter add dev $DEV parent ffff: protocol ip prio 50 u32 match ip src \ 0.0.0.0/0 police rate ${DOWNLINK}kbit burst 5k drop flowid :1
This is a heavily tuned version of the Wonder Shaper script that roams the Linux advanced routing and traffic control Web site.
Keep reading to find out how to install and use this script on your computer.
How to use the script
To use this script, you need to:
-
Install it to your computer
Copy the contents to your clipboard, then save it to a file named
rc.wshaper
in your/etc
directory. You may need to do this task as the root user, because the/etc
directory is off-limits for unprivileged users. -
Configure it. It's easy to set up.
- The line that starts with
DOWNLINK=
should be followed by your download bandwidth in kilobits per second, minus 5% to 10%. For example: if you have a 1000 Kbps link, you should set it between900
and950
. - The line that starts with
UPLINK=
should be followed by your upload speed minus 5% to 10%. - The line that starts with
DEV=
should contain the name of your network interface (typicallyeth0
-- check your computer's network configuration). -
Optional: set low- and high-priority ports.
The lines that start with
NOPRIOPORTSRC=
andHIPRIOPORTSRC=
can contain a quoted list of low- and high-priority ports (whose traffic will take a back seat in the face of regular traffic). The script already ships configured with ports for VNC (as high-priority), BitTorrent, Direct Connect and Gnutella.
- The line that starts with
-
Set it to run during startup.
In the file named
/etc/rc.local
on your computer, add a line that calls this script:#!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing. /etc/rc.wshaper exit 0
Take note: in some Linux variants, the file is named
/etc/rc.d/rc.local
. -
Reboot. Or run the command directly, if you know how to.
How do I know if it's doing anything?
Simple. You call it (with administrative privileges) using the status
argument on your favorite terminal program:
[~] > sudo /etc/rc.wshaper status Password: Queueing disciplines: qdisc htb 1: r2q 10 default 20 direct_packets_stat 0 Sent 72212097 bytes 206134 pkt (dropped 0, overlimits 231945 requeues 0) rate 0bit 0pps backlog 0b 66p requeues 0 qdisc sfq 10: parent 1:10 limit 128p quantum 1514b perturb 10sec Sent 5268314 bytes 97447 pkt (dropped 0, overlimits 0 requeues 0) rate 0bit 0pps backlog 0b 0p requeues 0 qdisc sfq 20: parent 1:20 limit 128p quantum 1514b perturb 10sec Sent 2002303 bytes 26155 pkt (dropped 0, overlimits 0 requeues 0) rate 0bit 0pps backlog 0b 0p requeues 0 qdisc sfq 30: parent 1:30 limit 128p quantum 1514b perturb 10sec Sent 64941480 bytes 82532 pkt (dropped 0, overlimits 0 requeues 0) rate 0bit 0pps backlog 72656b 66p requeues 0 qdisc ingress ffff: ---------------- Sent 113358865 bytes 167464 pkt (dropped 7565, overlimits 0 requeues 0) rate 0bit 0pps backlog 0b 0p requeues 0 Root class: class htb 1:1 root rate 120000bit ceil 120000bit burst 5Kb cburst 1659b Sent 72141381 bytes 206073 pkt (dropped 0, overlimits 0 requeues 0) rate 101536bit 37pps backlog 0b 0p requeues 0 lended: 24985 borrowed: 0 giants: 0 tokens: -9440 ctokens: -245643 Child classes: class htb 1:10 parent 1:1 leaf 10: prio 1 rate 120000bit ceil 120000bit burst 5Kb cburst 1659b Sent 5268314 bytes 97447 pkt (dropped 0, overlimits 0 requeues 0) rate 8304bit 19pps backlog 0b 0p requeues 0 lended: 97447 borrowed: 0 giants: 0 tokens: 346248 ctokens: 110045 class htb 1:20 parent 1:1 leaf 20: prio 2 rate 96000bit ceil 120000bit burst 5Kb cburst 1659b Sent 2002303 bytes 26155 pkt (dropped 0, overlimits 0 requeues 0) rate 2096bit 3pps backlog 0b 0p requeues 0 lended: 26155 borrowed: 0 giants: 0 tokens: 432128 ctokens: 109499 class htb 1:30 parent 1:1 leaf 30: prio 3 rate 72000bit ceil 120000bit burst 5Kb cburst 1659b Sent 64941480 bytes 82532 pkt (dropped 0, overlimits 0 requeues 0) rate 92136bit 16pps backlog 0b 61p requeues 0 lended: 57486 borrowed: 24985 giants: 0 tokens: -216810 ctokens: -125876 class htb 1:40 parent 1:1 leaf 30: prio 4 rate 72000bit ceil 120000bit burst 5Kb cburst 1659b Sent 64941480 bytes 82532 pkt (dropped 0, overlimits 0 requeues 0) rate 92136bit 16pps backlog 0b 61p requeues 0 lended: 57486 borrowed: 24985 giants: 0 tokens: -216810 ctokens: -125876
As you can deduce from the output of the script, there are four classes:
- 1:10: acknowledgements and interactive traffic (type of service
Minimize-Delay
) go here - 1:20: high-priority traffic get classified there
- 1:20: normal traffic goes here
- 1:30: low-priority traffic and bulk traffic (type of service
Maximize-Throughput
) goes here, and gets trumped by the first two classes
Lower classes trump higher classes.
You can see how many bytes have been sent in each class, and the speed (rate
) at which each class is operating.
How good is it?
Very good.
Obviously, if you're downloading twenty files simultaneously (which is the case with BitTorrent download managers), it won't give you a huge speedup, but you'll notice quite the difference in Web browsing speeds.
Perhaps the biggest speedup will be felt when using remote control applications, such as SSH or VNC.
Flaws in the script?
Yeah :-(. There's no easy way to classify and give priorities to incoming traffic, so only outbound traffic (uploads and the like) is prioritized. If you have a solution to this problem, contact me immediately -- I want to send you a case of beer.
However, the inbound traffic rate is policed by the script. Thus, no queues build up at your ISP, which means that you'll enjoy faster interactivity (Web browsing comes ti mind ;-))