Monday, April 20, 2009

Recently a local Internet service provider called TekSavvy e-mailed its clients about the fact that Bell was asking the CRTC to allow a to put a cap of 60 GB per month on its wholesale DSL.

Bell sells DSL services to Internet service providers. Essentially, it sells the link between your house and Internet service provider. The Internet service provider is responsible for linking you to the rest of the Internet. Bell is already throttling everyone claiming that it's trying to control congestion on the network. I am mighty suspicious of this claim.

This is what I sent to the CRTC:

It's important to foster competition between ISP in order to make sure that consumers can have a wide selection of billing plans / possibilities available so they can make the best decision for them. Bell should not be allowed to set monthly caps per user. The decision to do this should be up to the internet service provider. Mandating this destroys all sorts of potential pricing structures.

Pricing for wholesale DSL rate should be based on the scarcity of the resource in question. Capping bandwidth per user is an attempt to deal with bandwidth issues. If it's the number of megs per second causing the slowdown then it makes sense to bill wholesale DSL service based on that. It doesn't make sense to bill on that *and* some other thing, however.

If we are to have DSL service whole selling then it must be considered to be part of the spec that the DSL network be data neutral (no preferential throttling speedup or slowdown based on the data flying over the network; pretend it's encrypted) and user neutral (rate doesn't change based on which account I use or how much any account has used). This configuration sends the right supply/demand signals back to the ISP.

Consider that I don't use Sympatico or any other DSL ISP because they violate network neutrality by throttling certain specific protocols. If Sympatico continued to throttle certain protocols but other DSL ISPs did not I would have an alternative ISP to go to. This despite the fact that that other, none throttling ISP may have a badwidth cap in place at, say 30 or 40 gigs per month. The third party ISP in this example chose an different approach to dealing with their bandwidth issue.... The argument works for many other potential plans. Currently I'm on a plan with that limits maximum bandwidth speed to a relatively modest level but also provides a large download cap for a relatively high price. This sort of trade off is possible with the simple system mentioned above.

I would've kept going but there was a 2000 character limite and so I had to stop there. Here there was some of the stuff that was cut out.

Consider this:

By putting all of its throttling on the *DSL* half of the link it *guarantees* that ISPs won't be able to find innovative solutions to the bandwidth crunch. Given that there are many independent ISPs and only one Bell ISP (Sympatico) it's likely that if an innovative (and counter intuitive) approach to managing the bandwidth crunch were to be developed, it would be developed by a third party DSL ISP. This would essentially mean that sympatico would be vulnerable.

Have you ever seen a progress bar that goes from empty to full then starts over at the beginning again? I really hate those.

I had always assumed that progress bars were pretty uncontroversial. It wasn't until I worked at Intelerad for about a year that I found out that many people don't actually understand what progress bars are for, how they should work or how to write code to implement them.

When you present a progress bar to the user you're telling them:

1) That the computer is doing something that'll take a while.2) That the computer hasn't frozen or otherwise become unresponsive.3) Approximately how long the computer will be busy.

It's important to remember that a progress bar is not to display the progress some arbitrary chunk of code. If you think of a progress bar showing the progress through some function or chunk of work, you're likely to show multiple progress bars in a row where each filling of the progress bars will represent the progress through a particular task. Don't do this.

What the user actually wants to know is how long the computer will remain busy doing its thing. Alternatively, how long it will be until the computer returns a result. When you've filled up a progress bar and restarted it, you're messing with the user's head.

(Don't mess with the user's head)

A common worry when creating code that has a progress bar is that if you show progress bar for the entire time the computer is busy, and not for individual subtasks, then that code will not be reusable. It won't be reusable because you'll have to hard code the values you're setting the progressbar to in that function. As a result you won't be able to use that code with, say, another progressbar because the values that you need to set the progress bar to in that context will be different. 80% done for this progress bar might be only 40% done in a different context.

It's actually very easy to create little subroutines that only worry about the progress though their portion of the task and then wrap those progress meters into meta-progress meters to show the progress through any larger task. Here's how you do it.

Progress bar-fu:(n.: the ancient Japanese art of making progress bars that don't jerk the end-user around)

Think of the progress through the overall task as being the sum of the progress through each individual task. Looking at the problem this way it should become apparent that each sub task can look at its own progress as going from 0 to 100% with this value being a smaller proportion of the progress of the overall task.

Let's look at an example. Let's say we have an overall task composed of three subtasks. The first sub task is 40% of the overall task. The second sub task is 50% of the overall task. The last task is 10% of the overall task. Drawing this out your great little chart like the following:

Here we can see that the first subtask's progress, as a value that goes from 0% to 100%, is equal to the overall task progress going from 0% to 40%. All we need to do to convert the sub task progress to the progress through the overall task is to multiply it by .0.4 (or 40%).

This strategy composes nicely.

Let's say that our first sub task is composed of two subtasks. The first sub sub task goes from 0 to 30%.

We can calculate the value of the subtasks progress by multiplying the sub-subtask progress by 0.3. We can then see the sub sub task's contribution to the overall task by multiplying it by 0.3 then 0.4 (or 0.4 * 0.3 = 0.12). So when the sub sub task gets to 100% we will have completed 12% of the overall task.

Here' how you do this in code. I'm going to use java because lots of people use it, understand it and it's what I know.

First you need an interface like this:

public interface Progress { /** * @param progress number between 0 an 1 that signifies the progress through a task. */ void advance( double progress );}

You pass an object of this type to any function you want to track progress for. Like this:

You can then place this JProgress into a JFrame and send the Progress object to the CompositeProgressBar constructor and you're all set.

Congratulations. You are now masters of the first level of progress bar Fu. You can write a progress bar that accurately reflects the progress of the overall task, even when the overall task is made out of little, tiny pluggable pieces of code. What is more, those little tiny pluggable pieces of code can now be reused in different contexts, with different progress bars. This is truly a great day for the user.

The remaining question is, how do you get to level 2 of progress bar Fu? Ah, that is a good question young grasshopper.

What if, you have a task for which it is completely impossible to gauge how long the task will take?

What if, you have a task for which you have a rough estimate for how long it will take but, you have no way to increment the progress bar because your code is blocked doing something else. For example, it may be doing some I/O in a different thread. Alternatively, maybe running a third-party process and there's no way for you to get any feedback about what that process is doing. Now would you do?