HTML5 Canvas ‘strangeness’

I was experimenting with the Canvas tag, and the code below worked great on Firefox, but would not on Safari or Chrome:


function draw(img) {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var image = new Image();
image.src = "http://localhost:3000" + img;
var context = canvas.getContext("2d");

Quite baffling. No errors on the javascript console either. It took me a little while to figure out that the problem.

The problem is that the browser may load images simultaneously while executing your javascript If the image load is not complete, well, your image does not display properly, and as far as the browser is concerned, there is no problem. (interesting how firefox 4 beta worked every time)

The solution? Attach an event listener,



function draw(img) {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var image = new Image();
image.src = "http://localhost:3000" + img;
var context = canvas.getContext("2d");
image.onload = function () {

Notice the addition of the eventlistener and the onload. That fixed it.

Fun with websockets, Node.js and jQuery

Websockets have the potential to make a big difference to loading on webservers, and improve interactivity characteristics of client side.

Coupled with Redis for persistence and Node.js for a fast web server can make a huge difference to the performance of your web server. I will focus on websockets in this tutorial: Redis and Node.js will be covered later, and there are lots of good sources for them on the web.

I worked on a little experiment to see how Node.js & websockets work. If you are just getting started with websockets, this tutorial might help you out.

Make sure to use a browser that supports websockets. Firefox & Opera have removed support because of a security hole. I have tested with Chrome.

Client Setup
Here is some really simple HTML to build the demo:

[code lang="js"]
<!DOCTYPE html>
<title>Websocket test</title>
<script type="text/javascript" src=""></script>

<div class="dvStory">
<form id="fmStory">
<textarea id="taStory" rows="2" cols="20"></textarea>
<input type="submit" id="buStory" name="submit changes"/>

This will give you a text area and a submit button.

Let’s finish setting up the client. We’ll add some javascript to set up websockets

Add Javascript
We’ll set up some variables to use in javascript. The websocket code is really simple to setup and use

[code lang="js"]
<script type="text/javascript">
alert ("socket is null");
var fm = $("#fmStory");
var ta = $("#taStory");

function doOpen() {
var s= new WebSocket('ws://localhost:8081');
alert("socket open");
s.onopen = function () {
//s.send ("ok I am warmed up");
return s;

var socket = doOpen();

function sendData() {
// alert ("ta changed");
socket.send ( ta.val() );

doOpen() creates a new websocket, running at localhost port 8081, and sends a hello message to the server when the socket is opened. Pretty simple API. The variable socket gets initialized, and sendData() is called every time the client needs to receive data. Websockets are bidirectional, of course, so unlike regular HTTP connections, they can receive server initiated data, which needed other methods like Comet earlier (or usage of polling). We’ll look at how to recieve server data next.

[code lang="js"]
ta.change (function (event) {
$('#buStory').click (function () {
alert ("click event");
socket.send (ta.val());
return false;
socket.onmessage = function(event) {
//alert ("got message" +;


sendData gets called when a click even or a change event occurs. If you are not familiar with jQuery, just know that you can register for events and react to them, which is what ta.change() and $(‘#buStory’).click() do.
Finally, socket.onmessage is what gets executed when the server sends a message to the client. We just update the text area with the message pushed by the server.

This is the way the code works: Any client connected to the server will send a message to the server when a change event or a submit takes place. The Server will turn around and echo the change to all connected clients. So to try this out, have multiple windows open connected to the server.

Save the code in a file, client.html. You will be opening localhost:8081/client.html to try this out.

The Server Code
Download node.js and a nice library to make websocket usage more convenient,

Once you have installed it, type up the following code

get some libraries

[code lang="js"]
var sys = require("sys"),
path = require("path"),
http = require ("http"),
url = require ("url"),
fs = require("fs"),
debug = require("util"),
events = require("events");
// Library
var websocket = require('../lib/ws/server');

Create the webserver

[code lang="js"]
/ create web socket server
var server = websocket.createServer();
// listen on port 8081

Next, we need a way to have the server return HTML files. This part of the code is taken from the excellent tutorial at tutsplus

[code lang="js"]
function load_static_file(uri, response) {
var filename = path.join(process.cwd(), uri);

path.exists(filename, function(exists) {
if(!exists) {
response.sendHeader(404, {"Content-Type": "text/plain"});
response.write(filename + "404 Not Found\n");

fs.readFile(filename, "binary", function(err, file) {
if(err) {
response.sendHeader(500, {"Content-Type": "text/plain"});
response.write(err + "\n");

response.write(file, "binary");

Now, if our node.js server receives a regular HTTP call, we know it is looking for the client file , so we just return it

[code lang="js"]
server.addListener("request", function(req, res) {
var uri = url.parse(req.url).pathname;

So when the client connects with http://localhost:8081/client.html, the server will just return the HTML.

However, if the connection is a websocket one, here’s the code that gets invoked

[code lang="js"]
server.addListener("connection", function(conn) {
debug.print (" Yo, welcome!");
// when client writes something
conn.addListener("message", function(message) {
debug.print ("yo, got message " + message + "\n");
// iterate thorough all connected clients, and push this message
server.manager.forEach(function(connected_client) {
debug.print ("sending message to" + connected_client);
connected_client.write(JSON.stringify( + ": " + message));

What is happening here? We add a listener, which hangs around waiting for connections. When there is a connection, we wait for a message to come. When a message is received, we iterate over all the connections, and write it to all connected clients. debug.print can be used to debug on the server side.

Thats how simple using websockets is, and combined with node.js, they can be pretty awesome.

Should you roll over your IRA to a Roth?

There is some shockingly bad advice on the web about converting your traditional IRA to a Roth.The advice typically says that ‘Oh, you will grow your money tax free once it is rolled over, so you will end up with more money’. Even worse are statements like ‘the greater your expected rate of return, the more sense a Roth conversion makes’.

I am not a tax advisor, but I know


When I see it.

It is shocking to hear well respected tax advisors and other who you’d have expected to have take elementary math classes state this. let me disabuse you of this notion by presenting a simple example. But first, some background.

Let’s recap what the two IRA’s are. The traditional IRA, which is what most of us have, pays money in on a pre-tax basis: you have to pay taxes when you withdraw the money at retirement age, presumably when you are in a lower tax bracket than today.

In the Roth, on the other hand, you pay in money post-tax, and the money grows tax free. You can convert the Traditional to the Roth by paying taxes. The big change is that the limits on conversion – you had to earlier make less than a certain income – have been removed. Anyone can convert Traditional to roth by paying appropriate taxes.

For our example, the assumptions we make are

1. Whatever your expected rate of return is does not vary depending on whether it is a traditional or Roth IRA.

2. Your current tax rate and expected tax rate at retirement are the same. Let’s make this 20% (We will expand on this later)

Ok, here is a Math 101 explanation of what does and does not matter:

Let’s say that you have $1000 in your traditional IRA. Your money has grown 400% compounded at the point you withdraw money.

Scenario 1: No Roth

In scenario 1, you choose not to roll it to a Roth. How much money will you have at retirement?

Before taxes, you would have accumulated $1000*4 = $4000. The govt will swoop in and demand that you pay them 20%. So you will end up with $4000 – ($4000*.2) =$3200.

Note this down, kids: You will have $3200 in retirement if you do not roll over to a Roth.

Scenario 2: Roth Conversion

Let’s assume now, under presssure from your tax advisor, who presumably will have a little extra in his paycheck for giving you this advice, gets you to convert to a Roth. Let’s rerun our analysis.

Your tax bill (remember, we fixed our tax rate at 20%) = $1000 * .2 = 200.

Your tax free investment: = $800 (well, minus what you paid your advisor)

At 400% (Tax Free! Yay!) growth you will have: $800 *4 = $3200.

Wait, What? You end up with the same amount??

Yeah. As you learned in middle school, a*b = b*a.


If the expected tax rate at retirement is the same as your current tax rate, it matters not a whit whether you convert to Roth or not. You expected rate of return is irrelevant.

So what are relevant reasons for a Roth conversion?

There are subtleties to be aware of – after all, this is the US tax code.

The most obvious reason, already alluded to above, is the expected tax rate at retirement. if your expected retirement tax rate is going to be higher than your current, by all means, do the conversion – makes sense to pay less now. For many of us, this is not going to be true. Don’t do it if your expected tax rate in the future is going to be lower than your current.

One reason it might make sense to convert part of your traditional to a Roth is because of the  withdrawal regulations. at age 70.5, the IRS will take a penalty if you do not make a minimum withdrawal from your traditional. No such thing for the Roth.

Another subtle reason comes from the $200 tax bill that you paid up front for a conversion. If you were not using it for the roth conversion tax bill, you may have invested it – in a taxable account, which is subject to capital gains tax. The $200 will attract additional taxes.

Caveat Emptor!

Privacy is the new search quality

Search quality is not a distinguishing feature any longer

Google does provide the best search results. But do you care? DuckDuckGo’s search quality is almost as good. Do you care if you got the result you wanted as the very first result, or the third? Privacy is the new search quality.

Do you understand the privacy policies of search engines? If your answer is ‘I don’t care’, you are making a mistake. You SHOULD care.

Here is what Google‘s policy says:

When you access Google services, our servers automatically record information that your browser sends whenever you visit a website. These server logs may include information such as your web request, Internet Protocol address, browser type, browser language, the date and time of your request and one or more cookies that may uniquely identify your browser.

Google also specifically calls out that they can and will use this data for targeting ad content

Here is what DuckDuckGo says

… DuckDuckGo takes the approach to not collect any personal information by default. The decisions of whether and how to comply with law enforcement requests, whether and how to anonymize data, and how to best protect your information from hackers are out of our hands. Your search history is safe with us because it cannot be tied to you in any way.

Readability of the privacy policy

Unlike the ridiculous gobbledegook other search engines make you read (oh, BTW, if you are using Google, there are separate policies for DoubleClick & Postini) , DuckDuckGo’s founder, Gabriel Weinberg personally wrote the privacy policy for DuckDuckGo. You will be hard pressed to find something else on the web as well written. What a breath of fresh air for English Majors and Nerds alike !

HTTPS Everywhere

DDG now supports HTTPS everywhere . This means that when you search DDG and you are directed to a site like wikipedia, it will automatically use HTTPS

One Click

Get the information you need without having to click further. DDG is smart. when you enter a search term, it uses a bunch of sites (like wikipedia) to disambiguate and present definitions. Very often, this is quite sufficient for your search needs – no further clicks needed.

Keyboard Shortcuts

Use the keyboard to nagivate. For example, the down arrow takes you to the next search result

Best customer support. Period.

Every tried sending mail to Google complaining about something? Are you kidding me? It goes into some black hole.

Every time I have sent mail to DDG (about 3 times now) I have had a response – from Gabriel himself – in under 5 minutes. Or maybe it is someone pretending to be Gabriel, but the clone is every bit as smart as I suspect Gabriel is. At some point, this will stop scaling, but this is a company that cares about customers.


Give DDG a hint about where to go and go directly there

Wow, that almost sounds like an infomercial (BTW, I have no relations with DDG other than being a very satisfied customer)

Sorry, but Google looks tired compared to DDG. Forget all this BS about instant search. I know all your stats about how your revenues are a function of how many microseconds you shave off search results. Unless you are more honest about privacy, you will slowly but surely start losing market share

Comparing WWDC and Google I/O

I was lucky enough to have attended both WWDC and Google I/O this year. It was interesting comparing the two: There were clear cultural differences, differences in approaches and similarities in outcomes. Here are my thoughts:

1. You are lucky to be here vs Thanks for coming

It was quite clear to me that Apple considers me lucky to be able to attend WWDC. This was made obvious in several ways: Long, Long lines to get in, though it was well managed (and expected). The massive gift giving at Google (HTC Evo, Droid -what the heck were attendees supposed to do with 3 phones other than quickly sell two?)  vs the – oh wait, you were lucky enough to be standing in line to get into WWDC. All Google I/O sessions available to everyone vs very restricted distribution of WWDC sessions. The egalitarian $450 admission for I/O vs the $1600 for WWDC. Not to mention that after the two phone giveaways at I/O, you come out about $150 ahead, after some consultations with Craigslist.

Lunches at WWDC was quite horrible, compared to quite tolerable at I/O. (I am a vegetarian, so could not tell you much about the meat selections).

2. Slick and polished vs  Functional

No question, the presentations at WWDC were really polished. I was in awe. Presentations were incredible. So polished, so precise, so well put together and so well organized. I wonder how they rehearse them. I can’t remember a single incident where things did not go exactly to plan. Hats off to Apple engineers who did the presentations.

Not that the presentations at Google were bad. But they were what you’d expect a bunch of engineers to present. It totally lacked the polish. I think of Apple being a product management company, and Google being an engineering company. That explains the difference in presentations. Google could learn a thing or two from Apple here.

3. It’s HTML5 all the way, baby

Poor Adobe. Sorry buddy, but you’re so f’ed. All everyone at Google and Apple could talk about was HTML5. And it totally rocks. ( I will follow up with a post later on HTML5).

If you are doing web development, get on this bandwagon. This is one of those seminal events in technology. It has all the heavy hitters lined up behind it. Apple has put an extraordinary amount of effort into it, and the sessions on HTML5 were great at both I/O and WWDC. I preferred the Apple sessions just because of the additional polish in the presentations.

While the Adobe CEO was invited to the stage during the second day keynote, he got a very indifferent response. It was obvious to me – and I think most of the others – that Google was just inviting Adobe to the party to make noises about ‘openness’ not because they think flash has a future.

4. Baiting vs Ignoring

Vic Gundotra, the Google VP, was clearly going after Apple in his address with some nonsensical (IMO) talk about openness. Apple and Google have different business models, and they are executing to that. Some of the potshots were low blows, IMO. Jobs, and everyone else at WWDC, ignored Google for the most part – the feeling I got was that they were saying ‘eh? Android? What is that?’

5. Walk alone vs Partnerships

There was no partner pavilion at WWDC. I/O had a big one. WWDC is about Apple. I/O is about Google and friends

6. New friends and Old Enemies

Clearly, the Google vs Apple battle is now the new battle in town. The Microsoft vs Apple one is over. Apple spent a lot of time cozying upto Microsoft. Expect this partnership to deepen as they ally against their common enemy.

7. HTML5, again

This is where the enemies cross paths. Google and Apple clearly want HTML5 to win, and they work closely and deeply on advancing this. Safari 5 is pretty awesome, and a step ahead of chrome in HTML5 implementation.  Maybe Adobe can work on a nice implementation of an HTML5 editor


If Adobe is the clear loser with HTML5, Microsoft is going to get cleaned out in battle between the iPhone and Android devices. They should consider cutting their losses.

9. Focus, Focus, Focus

Apple made it very,very clear where they want developers to be: iPhone and iPad, XCode/iOS4 and HTML5. Thats it. forget MacOS. That is a sidenote. All the presentations were arranged accordingly.

On the other hand, I/O presented a smorgasbord of technologies, with no real underlying theme (well, maybe HTML5 & Android). Google Wave was still there . Buzz has a few sessions. There was even a session on engineering management. Huh? Please, attend the WWDC and understand how to run these.

10. The obvious

All the women at I/O were interviewed, as were all the women at WWDC. Both the ladies attending I/O and all three attending WWDC said they liked the sessions.

Did you attend either or both? Do you agree with my opinions? Let me know

rails with mysql: uninitialized constant MysqlCompat::MysqlRes

if you get this error on snow leopard, check to see which version of mysql is installed.

%> file `which mysql` <-- notice the backticks

The correct response is below

/usr/local/mysql/bin/mysql: Mach-O 64-bit executable x86_64

If you have 32 bit mysql installed, uninstall it (be sure to back up your databases first) and then install the 64 bit db. Uninstallation is simply removal of the /usr/local/mysql dir using sudo

Lies and damn lies

I found this ad in Newsweek. This one was breathtaking even by normal dubious standards that advertisments have.

Here is my beef with it:

1. See what the small print says. THere was a payment of $14,352 plus $648 annual premium. Somehow, that is equated to an initial payment of $15,000. How does that work? And then the return is computed on 22,005 based on an initial payment of $15,000. I dont get it.

The way I see it, the net payments were: $14,532 + ($648*10) = $20,832.

The internal rate of return on that (using (final/initial)^1/#years)-1)*100 = .54%. Far cry from 3.91%!

2. It is very interesting that they have chosen the time period from 9/30/1999 to 9/30/09. What if you had chosen a different time period? How about Dec 1994 to Dec 2004? The S&P 500 went from 45.54 to 120.87. That gives an annualized return of 10.25%. How much did the insurance pay out in that period ?

This kind of bad advertising from a large company is sad to see

Go for #3

One of the early – and best – career lessons came from my boss, when I was 2 years out of college.

I agonized over a design decision for a couple of days, and finally asked him to help me out. He was late to a meeting, so was rushing, but agreed to listen to me for 30 seconds.

I started describing the first of 3 options, and his eyes started glazing over.

He told me ‘Stop. Just go for option #3′.

‘What!?’ I asked. ‘ I have not even describe the options 2 and 3 to you’.

His answer has stayed with me throughout the rest of my career.

‘Look’, he said ‘ I know you, and I know how you think. So let me be straight with you’.

‘Option #1 is going to be too expensive to implement. Forget that’.

‘Option #2 – forget that. You are not smart enough to implement it’.

‘So, just go for #3′.

Ever since, Whenever I am faced with design choices, I write down 3 options. Then I carefully scratch out #1 and #2, and go for #3. Works like a charm