Vishnu Gopal

blog.vishnugopal.com

Category: Uncategorized

The Art of Fixing Code

The title isn’t original, but it’s apt and describes my feelings exactly. Bulleted, and also referred to as Vishnu’s Commandments for Fixing Code:

  1. Fix The Fucking Problem (hereafter FTFP)

    When you’re faced with a bug, a calamity, a loss of limb, you solve the problem. Don’t worry about its causes, its probable antecedents, which commit broke your painfully arranged view of the multiverse or whether you’ll earn a PeeEtchDee by writing a paper about good software engineering practices. Instead, you FTFP.

    Only after you’ve FTFP, shall you think about anything ancillary. Only afterwords shall you blog or tweet about it or submit it to our humorous overlords. Capish?

  2. Next, FTFP as if your ass is on fire.

    Downtime sucks. If a marginally large system used by a non-trivial number of users (by which I refer not to your blog which your mom and your imaginary girlfriend reads) goes down the rabbithole, a lot of people will complain. If you work for Initech, Lumbergh will cluck his tongue and hand you a pink slip if you mess up too often. Forget nine-nines of reliability, if you manage a month with just 5 mins downtime, it’s great.

    I’ll also extrapolate this from TDD: “Write a test, write the minimum amount of code for the test to pass, refactor, write more tests.” becomes “Figure out the problem, write the minimum amount of code that fixes
    the problem
    , refactor, find more problems.”

  3. Log. Write logs to Disk. Backup & rotate Logs.

    In any after-action report, you’ll want to figure out why the Problem happened. What went wrong. For this you need logs from when it happened. Often you’ll notice that it’s a periodic bug which slowly got worse as your system added in more users, so you’ll want to figure out exactly when it happened, and when the issue escalated. For this you’ll need to log properly and backup those gzipped logs. Thumb rule: for the first nine months of any production system, logging should be enabled with the maximum possible verbosity. This includes connected systems, like for example, Database Logging.

  4. Use Git already, nitwit!

    It’s pretty much what everybody should use. Easy, quick code commits and can even serve as a quick and dirty deployer too. Git allows you to hotchpotch solutions in case of emergencies. There will be instances when you want to short-circuit every code review check and just deploy the thing goddammit and nothing beats Git, for now.

  5. Use an automatic deployment tool.

    Your deploy should be just one command, or a click of the button. Hooking up before-commit hooks is okay as long as it doesn’t take an eternity.

  6. Make pretty downtime notices so people know you are at least trying.

    Being apathetic sucks. Giving an impression of being apathetic when you are working hard to save your application sucks harder because of stupidity. So don’t be stupid. Communicate. Make twitter work for you or for the old-fashioned, have a mailing list or an RSS feed. Your blog shouldn’t go down at the same time as your site so keep it on a different server—wtf are you doing writing a blog app anyways—outsource that to people who know better.

  7. Learn the ins and outs of your deploy OS of choice

    It’s not enough to be a Gee Whiz programmer. Learn your OS inside out. If you’re on *nix (like real men) then this involves figuring out what to do when your load average goes through the roof, your SQL engine hogs CPU, your hard-disk fills up or your webserver restarts. Learn about commands like: top, iftop, iotop, uptime and the entire /proc magic filesystem. It’ll help you diagnose code and issues. For blacker magic, learn about strace and dtrace and how to debug difficult issues. All this comes later though—remember the golden rule: FTFP, so the first take should always be to Google your error.

  8. Don’t put all your eggs in one basket

    Do trust in Murphy, he’s eternally right. Things will fuck up. Instead of preventing it, plan for contingencies and try to recover from them fast. Have scenarios where bad things happen to your application. Have a load balanced implementation the first thing for chrissake! Have a DB in a master-slave configuration the instant you can afford it. Have a system where provisioning servers doesn’t take days. Move as much infrastructure as you can to the cloud where you don’t have to maintain it directly.

  9. Delegate the Debugging

    This might be harder to do because you’ve got to pump up your adrenalin and stay in the zone to figure out problems and implement quicker solutions, but often, three or four helping hands work much better at solving problems—especially when other people can help you cross-reference data to try to come up with probable cause. Remember, speed is key.

    Surround yourself with people who are smarter than you too. That helps to negate your stupidity. Own up to mistakes and implement solutions fast.

  10. Have a Staging Server (or Replicate Production as closely as possible)

    The worst problems are those that happen only on production systems and can never be replicated in development. Remember: OSX is not Linux, minor version differences often introduce incompatible interfaces (I’m looking at you, Rubygems and PHP) and stuff breaks when you add something new without testing it on your deployment OS of choice.

    If you are making any drastic changes to the architecture, test in on a staging server (or if you can’t afford it, a password-protected subdomain) in live conditions before switching, it’ll save you loads of trouble.

  11. Prevention is better than Cure

    Do TDD or have a good test suite. Stuff will break far less often then. Educate your coders to have decent S/W engineering practices. Indent code and name variables uniformly. Raise exceptions and use assertions within your code. Use transactions too so when stuff breaks it doesn’t affect a lot of other important elements. Learn how to use a Queue and how important that is in modern production systems. Don’t abuse an RDMS for tasks it wasn’t meant for. Learn about newer key-value storage DBs. Beware of caching—it introduces subtle errors and problems, but learn to love it too, without it, you’ll never scale. Write readable code and document it both within and separately.

Meera’s Blog

Meera's BlogMeera’s new blog is here: meerarnair.wordpress.com. (She also has a twitter account btw @meeranair).

Women, Diversity & Discrimination

Background: Presentations that include female nudity and references to porn in professional presentations. The first incident occurred at GoGaRuCo the Ruby conference in April, the second and far more blatant one at the Flashbelt conference just two days ago.

This is my take on the issue, and my personal experiences with these kinds of incidents.

Incident one: I had gone to the Bangalore FOSS.in conference about two years ago. An extremely attractive lady from linuxchix came up on stage to speak on The Black Art of Makefiles. As has happened many a time before to many a speaker’s laptop, hers refused to play nice with the on-screen projector and the slides just wouldn’t come up. Yes, probably a screen resolution mixup. What was unusual though was the ten guys who rushed up on stage and started working on her laptop. They tried for a minute or two to fix the problem (without success) before the lady eloquently managed a few keystrokes in. And voila, the slides came up and the crowd dispersed, sheepishly. Yes, the lady knew best—it was her laptop after all.

Incident two: One of my friends is studying for her MBA at a good institute where companies come up to place people for summer internships. An interesting statistic: 80% of people who got placed in high-profile companies were girls, and a reputed technical MNC only gave out internships to girls. I theorize that this is because as a rule, girls sell products much better than guys.

Fact: There are subtle (and not) gender differences in the technical community that’s visible every day. While most often this is genuine discrimination, sometimes (as in incident two) it’s biased towards women too.

Fact two: Not all discrimination is deliberate. I’m pretty sure the Ruby presenter was just trying to be “edgy” (Ruby is much more conducive towards such non-mainstream behavior) but ended up offending the women in the audience. I’m not sure many women realize this, but men do not have an internal radar on the things that offend women – this is a general extension of the “cluelessness” that is often attributed to us, albeit with more serious consequences in this case.


Whatever the case may be, there’s one solid fact. We genuinely need diversity in the technical community – a broader opinion and insight on every topic just leads to a better community and this is true however cutting-edge it might pretend to be. Most of the people do want to encourage this diversity too and not make women uncomfortable at formal presentations and in a crowd which is >80% men.

One suggestion. I know women are not confrontational, but early intervention will help – if you feel uncomfortable, speak out, and the earlier the better. If you are in a mailing list and there’s a sexist troll, speak out and say you are not happy. Some men do listen (and those men are usually the ones who are in charge).

I’ve got to admit the blog posts and news coverage have made me think on what is appropriate behavior in public. Some people want to portray conforming behavior as a dampener to creativity but that’s hardly the case – you always follow some sort of rules (for e.g. imagine a guy taking off his clothes on stage – I’m certain the 80% won’t be amused). Creativity within constraints is a challenge and if you want a discerning minority to listen in and come up with suggestions, make sure your slides do not offend too.

One more thing—As many women have pointed out in the Flashbelt incident comments, it’s not the bawdy humor that’s the problem—it’s the context. If you want an analogy, imagine yourself as the only person in a crowd of women all laughing at a joke about how size does matter after all.

Identity Changes

So I was a very early Internet user. Not so early as Tim Berners Lee, but early enough to see Internet access begin in India – those dialup modems were excruciating: they promised much but delivered little. I remember a service early enough in the Web 1.0 era that allowed people to register domains for free (yes, without paying a buck). These guys (I’ve forgotten the name) made money by framing the site contents and delivering flash and scroll ads up top. Needless to say, they quickly went out of business. But I remember I had a vishnugopal.com registered with them way back then.

Since I’ve been “alive” on the net for close to ten years now, I’ve left traces under many different identities. Very early on, it was uncheckedramblings, which was the name of a blog that I made at blogspot.com – vysnu.com evolved from those humble beginnings. Concurrently, my primary identity on the web was thehitchhiker and the necessary variants that had numerical prefixes, suffixes and substitutions to it. My Yahoo ID until a couple of years ago was thehitchhiker_123. I had another alias during this time created for shady purposes. I used q— to write unconventional stories. Then (in a fit of originality) I combined that ID with thehitchhiker to create QHitcH (often spelled all lowercase as qhitch). That is still my Skype ID.

So just to recap, until now I’ve had four identities on the web. Till recently, I maintained my portfolio site at vish.in, my blog at vysnu.com and my twitter account was named vishmaker.

While it’s nice to be creative, it’s also nice (and SEO sensible) to be consistent. And what better name to brand than your real name? So it’s vishnugopal everywhere from now on.

Inspiration: The excellent Securing Your Online Identity article, an extract below:

Ideally you should implement one consistent online name that can be used across many different platforms. It's best if your online name is the same as your offline name, but you may find it necessary to make them different for certain reasons. You may also decide to use a different name for your business presence and your personal communications. Generally the higher the consistency you can achieve the better.

via Securing your online identity | creativebits.

Aside: It’s a sad fact of the web that none of those early avatars are visible now. It’d have been nice if HTTP behaved more like source control – web.archive.org didn’t consider any of my sites important enough to store.

Movieonline.in

It’s the first time in a while that I’m writing about something Torque has done, and although I wasn’t involved in the making of the site, it’s a really good creation which you should know about.

Drumroll… Movieonline.in. It’s networked with good theaters in Thiruvananthapuram and Ernakulam and you can book tickets, choose seats, pay via credit card, and get your ticket delivered via email and sms. It’s a pretty cool creation all round and compared to the atrocity that is PVRCinemas (I tried two times to register only to give up), a joy to use.

Account creation is fast. Enter your name, email address and password and you are good to go instantly, there’s not even a page refresh. That really sets the tone of the site: choosing the movie as well as the date is a simple drop down. There was a bit of a delay when I selected my seat but it cleared up quickly and I was taken to a CCAvenue screen where I typed in my credit card details and booked the ticket. It’s Rs. 55/- per ticket so there is a bit of an overhead, but chalk it up to the petrol costs you spend if you drive there manually to book and it seems very reasonable.

All in all, a very good effort.

Btw, I’m going to see Ore Kadal this Saturday. Me, mom and bro. Have heard good things about the movie.

IP Address to Country in Erlang: ip2country-erlang

Inspired by the latest Ruby Quiz: IP to Country: #139, I coded up a utility to map ip addresses to country codes in erlang. It’s available on google-code at
http://code.google.com/p/ip2country-erlang/
.

Some experiences while making this thing work:

  1. It took me the better part of six hours to get this running. I suspect if I’d done this with Ruby, I’d have completed an elegant, fast solution in less than a half hour. However I did make this harder for me (see below).
  2. It uses the in-memory database that Erlang has: mnesia. There’s functions in there to populate the mnesia table with the csv file and then perform lookups on it.
  3. Higher-order functions is the name of the game. For just about every useful thing from looping down to iteration, to mapping elements of a list. Coming from a non-functional background, I find this very hard to grasp still. Also: non-mutable state. Count +=1 doesn’t work. [So how do you implement a counter? Recurse with a parameter].
  4. I miss the Ruby Standard Library very very badly. Of all the languages I’ve used, Ruby’s is the most concise and clear and manages to have just about every function you need in there. String manipulation in Erlang esp. is very cumbersome. Somebody probably should port over all the functions asap. lists:join, string:delete, string:delete_if etc. would be invaluable.
  5. The comma, semi-colons and fullstop craze (along with proper indentation) is sometimes very confusing. The rules are actually easy to remember, but when I nest functions using funs, I find I lose track of where I am and what’s supposed to happen. I started programming this using Aquamacs but it crashed on me midway while using the inbuilt shell. I hate stuff which crashes so I switched to Textmate’s erlang mode which isn’t as functional but does a decent job of parenthesis matching and auto-indent.
  6. Mnesia is a joy to use. I spent a lot of time just playing around with many examples because it’s fun to make a record, dump it and use list comprehensions to perform selects. It’s way more intuitive than using SQL. Witness this fragment:
    
      qlc:q([X#ip_address_map.country_code || X <- mnesia:table(ip_address_map),
    		     X#ip_address_map.range_from =< Ip_address_as_integer,
    		     X#ip_address_map.range_to >= Ip_address_as_integer
    			]).
    
    

    That actually just says: get the country code for all X where X is an mnesia table of type ip_address_map and where X’s ip_ranges are within range_from and range_to. No SQL and exactly as you’d do within the language.

  7. It feels very awkward to get Erlang to be a shell scripting language. I’m not sure escript is even supported anymore but it does work. Erlang is not for scripting.
  8. The whole exercise reminded me of my extreme newbiness. I’ve been dabbling off and on in Erlang for over four months now and still I’m not at a stage where I can code in it off the top of my head (this hasn’t happened before with any language, but admittedly all the others were just procedural ones). The problem is I’m not using it for anything big. That should hopefully change someday. [Not much hope, but does somebody want to hire me to work on erlang or lisp? :-) ]
  9. The erlang mailing lists help a lot. Just being there you soak up a lot of info.
  10. Concurrent erlang is another ball game altogether.

Get started!

JRuby Compiler Update, and a Nice Peformance Milestone

JRuby Compiler Update, and a Nice Peformance Milestone. Cool stuff.

Comment spam

I’ve just debuted a new way to stop comment spam on this site (#5 on this list). It’s inaccessible for people with Javascript turned off, but even Akismet wasn’t helping enough for me.

SlideShare Twitter Mashup

So here’s a SlideShare/Twitter Mashup (command-line ruby code) that does these things:

  1. Gets buzzwords from Twitter. It does this by analyzing tweets and getting popular words (filtering out common ones) with the Twitter API.
  2. Gets the most popular buzz word and searches the SlideShare tag database with it (using the SlideShare API).
  3. Prints out the buzzword and the slideshows that’s associated with it.

The source code might not be a great example of filtering and getting popular words, but it’s a good demo of how simple the Twitter and SlideShare APIs are (REST yay) and how easy Hpricot makes parsing XML docs.

There’s a zip (with the source code, common_words.txt, twitter_words.txt) here: slideshare_twitter.zip. Enjoy. :-)

Basic SCM with Subversion & Trac

This is a talk I gave at Torque today. It’s meant to a very basic intro to SCM with Subversion and Trac.

Two Movies

Just an observation. If my bittorrent goes flat out, I can download a movie in ten hours. In a day, I can download two movies, which is about what a healthy adult should watch in a day. I wonder what’ll happen when my bandwidth doubles. (Oh, and people who only go by DVD-rips – or worse – can… wait.) So what did I watch recently? Bourne Ultimatum, Bridge to Terabithia, and Transformers. In reverse chronological order.

orkut

The new orkut look is frankly amazing. It’s got the Google sense of simplicity finally and looks much less crowded than even Facebook! (if it hasn’t rolled into your account yet, it will).

Tail Recursion

Ponder this:

fact (0) ->
	1;
fact (N) ->
	N * fact (N - 1).

versus this:

fact(N) ->
	fact_helper(N, 1).
fact_helper(1, T) ->
	T;
fact_helper(N, T) ->
	fact_helper(N - 1, T * N).

The advantage of learning Erlang (albeit very slowly, with lots of interruptions) is that it directly introduces a lot of concepts I’ve been marginally aware of before. For instance, the second example implements factorial using tail recursion. The advantage is that a compiler doesn’t have to implement a call-stack when playing with arguments. See wikipedia entry.

Me on a Vallam

Yesterday, I got into a Vallam and traveled from Malakkara to Aranmula and back. It was wonderful.

Since I’m a newbie at everything from wearing a mundu (dhothi) properly to holding the nayambu (oar), it was a pretty interesting experience at first. You have to madakikutthu the mundu (fold the mundu over so that it looks like a knee-length skirt) so that you can sit comfortably in it and after a few tries, I managed to do that. [aside: I'm pretty sure true-blood Malayalis would wince at this point. My only advice: please don't read on]. The vallam itself is about twenty to thirty metres long and seems to weigh a ton, but it’s constructed so well that just a finger-touch can move it on the water (trust me, I tried it). When about forty people get onto it, it remains amazingly steady and sure, although the getting in (and out) is an experience that’ll rival a roller coaster.

There are planks that go cross-wise the breadth and parallel to it from the edges so that you don’t usually step into the wet bottom of the boat. You sit at the very edge locking your legs back and across and it’s probably the closest I’ve come to the water without getting wet. It was also interesting learning how to row properly. The nayambu is a thick wooden oar with a longer handle. There’s a circular piece at the top that you’re supposed to grip with one hand, the other holding the top of the flaring edge firmly. And then you row. Easier said than done of course :-) . After splashing my fellow boatmates about a thousand times, I managed to get the hang of it. A chetan sitting behind me (who bore much of the brunt of my attack on water) commented on the return-trip that for a newbie I did it very well indeed [this made my day :-) ].

What distinguishes the Aranmula Vallam from its variations across Kerala (and the world) is the Vallapattu (boat-song). Resonating exactly with the rhythm of the oars, it’s a beautiful counterpoint to the entire experience: if the song moves faster, you instinctively row faster, and it’s so constructed (and sung) so that there are periods of relative inactivity and bursts of speed. It’s uber-wonderful.

The most common verse is this:

Thithithara thithithey thithey theke they they tho[..]om

The ‘th’ is a sound which is not in english: a cross between the t in ‘them’ and ‘tarrif’, also notice the alliteration. The [..] stands for a longer -o-, lengthening with an increase in exuberance.

It took around forty-five minutes to travel upriver and about ten minutes less to travel down. Not exactly fast (takes about ten minutes by car). I’ll estimate the top speeds to be around 25kmph, although this was not a race. I’m pretty sure though that more than the rowing, it’s the people who stand at the very behind of the boat (at an increased height) and who steer it – esp. the person who holds the odanayambu – who holds the key to a victory in a race. The rowers pretty much row as they please and unlike canoeing, it’s a game more of enthusiasm still rather than skill. I expect someone enterprising will change this soon: just off the top of my head, introducing pacing techniques and regular practice will increase the average speed of a boat considerably. Of course, then, it’ll cease to be fun and be serious sport, which is not the idea.

Me? I had a lot of fun.

Onam Lunch

Also see all the photos at Flickr, provides a really nice glimpse of the Onam world.

Reg. the facebook code leak

Surprise, surprise! Facebook code sucks as much as anything else out there. For people who don’t get the sarcasm, it’s what gets stuffed onto the browser that matters in the end. Having said that, clean aesthetics and a professional layout, a pluggable architecture, and even a PhD. paper doesn’t mean your code is of the Field-Medal caliber. Capish? (Bonus: funny comments).

DRY CSS

When I first thought of writing this post, my ideas were more about describing a good CSS organization and using reusable stylesheets. There are two tips in this area that I still recommend:

An element can have multiple classes: It’s a pretty simple idea, but isolate out layout styles and presentation styles. Even fonts and coloring. Make reusable classes as much as possible. A design like this rocks, esp. if it includes a small description of the classes used at the top of the .css file. At any point you feel an urge to create a new class, resist the urge and try to recreate the functionality using already existing ones. Break older classes further if you have to.

For e.g.:

.warn {
  color: red;
}

.top {
  position: absolute;
  top: 5px;
}

And this html:

<p class="warn top">You cannot do that, it'll wreck havoc!</p>

… is way better than combining those tasks. Why? Because you can reuse those classes.

Keep your page-specific CSS structured by an ID on the body: Again, a pretty simple idea, the <body> tag can take an ID that can be an indicator of the page name. Use that to create special styles for that page alone.

Example: you want the warning on product pages to appear in blue instead of the usual red, and you want more padding on top:

#product-page .warn {
  color: blue;
}

#product-page .top {
  position: absolute;
  top: 10px;
}

with this HTML:

...
<body id="product-page">
...
<p class="warn top">You cannot do that, it'll wreck havoc!</p>
...
</body>

The advantage is that you don’t hack the CSS or add more styles. It just works.

I have more CSS organization tips, but the above two have worked wonders in 90% of the projects I’ve been involved in. Let’s move on to using tools to write better CSS.

Use a CSS generator: In the Ruby/Rails world where I mostly live nowadays, there’s an excellent plugin called cssdryer. Using this, the CSS above becomes much cleaner:

#product-page {
  .warn {
    color: blue;
  }

  .top {
    position: absolute;
    top: 10px;
  }
}

… which is lovely. Finally, nested tags! And variables, and all the power of ruby! [There's also Sass]

If you are not in ruby land, use a CSS pre-processor. This article uses the m4 macro processor to generate DRY CSS.

Now, here’s one more lovely tip. Use a CSS framework. The most appealing one (altho in beta) is blueprint, since it only does a sweet grid system and good typography. Yahoo’s Grids seem bloated.

MiniPosts fix

This is a fix for the excellent Miniposts plugin by Morgan Doocy. There’s a miniposts2 variant that includes this fix as well, but since I don’t use widgets yet (or maybe will never) here’s the fix. Took me around a half hour of hacking. Thanks to this excellent guide. [The problem was every time somebody commented I lost the 'mini-postiness' of the post. Kinda nasty.]

mini-postsphp.txt and just the diff.

Fastmail Bad

I’ve just noticed that people who’ve been trying to contact me via my sent.com email address haven’t been reaching me. This is distressing because at one time I thought Fastmail would rule the world. Now they can’t even forward mail properly. I’ve changed my email to Google’s solution wherever relevant.

JRuby/Glassfish Investigation

I’ve been keeping an eye on the JRuby scene for a while now and I recently went about benchmarking again. JRuby is interesting because it has the potential to bring robust Java deployment and tools to the Ruby world.

I made a simple widgets application as outlined here and installed JRuby/Glassfish as outlined here (both great articles at AD TechFL) and then proceeded to benchmark:

Glassfish/Jruby on httperf:

Elena:~/Applications/jruby/lib vishnu$ time httperf --client=0/1 --server=localhost --port=8080 --uri=/jruby-demo/widgets/list --send-buffer=4096 --recv-buffer=16384 --num-conns=480 --rate=60
httperf --client=0/1 --server=localhost --port=8080 --uri=/jruby-demo/widgets/list --rate=60 --send-buffer=4096 --recv-buffer=16384 --num-conns=480 --num-calls=1
httperf: warning: open file limit > FD_SETSIZE; limiting max. # of open files to FD_SETSIZE
Maximum connect burst length: 2

Total: connections 480 requests 480 replies 480 test-duration 7.999 s

Connection rate: 60.0 conn/s (16.7 ms/conn, <=7 concurrent connections)
Connection time [ms]: min 1.4 avg 24.6 max 251.3 median 15.5 stddev 35.7
Connection time [ms]: connect 0.1
Connection length [replies/conn]: 1.000

Request rate: 60.0 req/s (16.7 ms/req)
Request size [B]: 83.0

Reply rate [replies/s]: min 60.0 avg 60.0 max 60.0 stddev 0.0 (1 samples)
Reply time [ms]: response 24.5 transfer 0.0
Reply size [B]: header 360.0 content 1077.0 footer 0.0 (total 1437.0)
Reply status: 1xx=0 2xx=438 3xx=0 4xx=0 5xx=42

CPU time [s]: user 1.42 system 5.79 (user 17.7% system 72.4% total 90.1%)
Net I/O: 89.1 KB/s (0.7*10^6 bps)

Errors: total 0 client-timo 0 socket-timo 0 connrefused 0 connreset 0
Errors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0

real    0m8.008s
user    0m1.418s
sys     0m5.799s

Glassfish/Jruby on ab:

Elena:~/Applications/jruby/lib vishnu$ ab -n400 http://localhost:8080/jruby-demo/widgets/show/1
This is ApacheBench, Version 1.3d  apache-1.3
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Finished 400 requests
Server Software:        Sun
Server Hostname:        localhost
Server Port:            8080

Document Path:          /jruby-demo/widgets/show/1
Document Length:        611 bytes

Concurrency Level:      1
Time taken for tests:   8.551 seconds
Complete requests:      400
Failed requests:        0
Broken pipe errors:     0
Total transferred:      397600 bytes
HTML transferred:       244400 bytes
Requests per second:    46.78 [#/sec] (mean)
Time per request:       21.38 [ms] (mean)
Time per request:       21.38 [ms] (mean, across all concurrent requests)
Transfer rate:          46.50 [Kbytes/sec] received

Connnection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0     0    0.0      0     0
Processing:    13    21   52.6     16  1019
Waiting:       13    21   52.6     16  1019
Total:         13    21   52.6     16  1019

Percentage of the requests served within a certain time (ms)
  50%     16
  66%     17
  75%     17
  80%     17
  90%     18
  95%     20
  98%     37
  99%    116
 100%   1019 (last request)

Let’s compare. Here’s how a single Mongrel/C does with httperf:

Elena:~/Applications/jruby/lib vishnu$ time httperf --client=0/1 --server=localhost --port=3000 --uri=/widgets/list --send-buffer=4096 --recv-buffer=16384 --num-conns=480 --rate=30
httperf --client=0/1 --server=localhost --port=3000 --uri=/widgets/list --rate=30 --send-buffer=4096 --recv-buffer=16384 --num-conns=480 --num-calls=1
httperf: warning: open file limit > FD_SETSIZE; limiting max. # of open files to FD_SETSIZE
Maximum connect burst length: 3

Total: connections 480 requests 480 replies 480 test-duration 16.009 s

Connection rate: 30.0 conn/s (33.4 ms/conn, <=18 concurrent connections)
Connection time [ms]: min 9.0 avg 56.4 max 607.6 median 9.5 stddev 99.4
Connection time [ms]: connect 0.2
Connection length [replies/conn]: 1.000

Request rate: 30.0 req/s (33.4 ms/req)
Request size [B]: 72.0

Reply rate [replies/s]: min 29.4 avg 29.8 max 30.0 stddev 0.3 (3 samples)
Reply time [ms]: response 55.7 transfer 0.5
Reply size [B]: header 278.0 content 1011.0 footer 0.0 (total 1289.0)
Reply status: 1xx=0 2xx=480 3xx=0 4xx=0 5xx=0

CPU time [s]: user 3.91 system 11.35 (user 24.4% system 70.9% total 95.3%)
Net I/O: 39.9 KB/s (0.3*10^6 bps)

Errors: total 0 client-timo 0 socket-timo 0 connrefused 0 connreset 0
Errors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0

real    0m16.017s
user    0m3.912s
sys     0m11.354s

And Mongrel/C with ab:

Elena:~/Applications/jruby/lib vishnu$ ab -n400 http://localhost:3000/widgets/list
This is ApacheBench, Version 1.3d  apache-1.3
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Finished 400 requests
Server Software:        Mongrel
Server Hostname:        localhost
Server Port:            3000

Document Path:          /widgets/list
Document Length:        1011 bytes

Concurrency Level:      1
Time taken for tests:   7.974 seconds
Complete requests:      400
Failed requests:        0
Broken pipe errors:     0
Total transferred:      515600 bytes
HTML transferred:       404400 bytes
Requests per second:    50.16 [#/sec] (mean)
Time per request:       19.93 [ms] (mean)
Time per request:       19.93 [ms] (mean, across all concurrent requests)
Transfer rate:          64.66 [Kbytes/sec] received

Connnection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0     0    0.0      0     0
Processing:     9    19   63.4     11  1167
Waiting:        9    19   63.4     11  1167
Total:          9    19   63.4     11  1167

Percentage of the requests served within a certain time (ms)
  50%     11
  66%     12
  75%     12
  80%     12
  90%     13
  95%     15
  98%    113
  99%    149
 100%   1167 (last request)

Observations

  • Advantage: For the same number of connections, Glassfish/Jruby versus a single instance Mongrel/C has twice the reply rate in half the benchmark time.
  • Disadvantage: Request latency is more for Glassfish/Jruby. (around 5ms av. more)
  • Disadvantage: JRuby Ruby/Rails support is not perfect but very good.
  • Advantage: Much simpler to set up. Copy the war file to the server and deployment is done, autodeployment is also possible w/o restarting Glassfish.
  • Advantage: Much simpler to install and get going on the server, just requires a JDK, glassfish installed anywhere, etc.
  • Advantage: Runs on Java, so Java deployment experience will do.
  • Disadvantage: Does not support C library extensions for Ruby, question: how many of them are there & useful (memcached?) ?
  • Advantage: Supports Java libraries kind of easily, again question: how many of them are there, useful and relevant?
  • Question: This benchmark is versus a single mongrel, how does cluster vs. cluster compare?
  • Question: Is glassfish clustering easy? Observation: mongrel clustering is cumbersome at present. Maybe swiftiply will help there with dynamic addition of mongrels?
Follow

Get every new post delivered to your Inbox.

Join 4,618 other followers