Pythious Syntactum

Note: This entry has been restored from old archives.

Time for a little Python “spot the difference” game! I’ve been working primarily with Python lately and a few weeks ago I found this hideous performance bug lurking in my code.

This:

setHash = {}
for featureSet in featureSets:
    for feature in featureSet:
        if feature not in setHash.keys():
            setHash[feature] = []
        setHash[feature].append(featureSet)

Versus this:

setHash = {}
for featureSet in featureSets:
    for feature in featureSet:
        if not setHash.has_key(feature):
            setHash[feature] = []
        setHash[feature].append(featureSet)

Now, consider that I have huge data sets. Guess what happens? Yes, that’s right Tommy! The first example is much slower, in fact it goes 1000 times slower. Beware the Indictkeys, my script! The its that rate, the keys that come! Beware the Hashhash loop, and crypt the pythious Syntactum.

The lesson here is: remember has_key

On reflection the wrongness of what I originally wrote seems obvious; I don’t know exactly what happens “under the hood” but I can probably make a fairly accurate guess. It just goes to show that even in a language as pleasant to work with as Python it isn’t too difficult to trip yourself up with simple, everyday foolishness.

[Of course, there’s always going to be other ways to do it!
It does look neater without the has_key]

Bug Challenged

Note: This entry has been restored from old archives.

You know you’ve truly left the land of the living when you’ve got no bugs left in the bug tracking system – even finally disposed of bug 578; ah, those were the days. Greetings from Hades.

Bug 578 was filed back in the old ‘level 4′ era I believe, when we even had the CEO doing some QA work and possibly even before the great Applications Schism. What do we do with ourselves now as our cells divide and multiply, reaching across the globe with our newly grown appendages.

It seems like an awfully long time, I’ve been working now for almost as long as I was hanging around Uni. Time, as they say, can really fly – such a hurry to what end?

You run and you run to catch up with the sun, but it’s sinking – racing around to come up behind you again. -PF

Office Space

Note: This entry has been restored from old archives.

I get upset every time bastards like Mr JoelOnSoftware write about their office setups.

  • Crap Chair – check
  • Single CRT Monitor – check
  • Open Noisy Office – CHECK
  • Wear headphones to combat distractions – CHECK
  • Realise that all this is very badcheck

(Note: I don’t actually work in an office of my current employer; our office back in Sydney would score better than my current location if compared against the points in Joel’s article – but not a great deal better, but we fit into the ‘it’s hard to do these thing if you’re a VC company‘ category so it can be a bit hard, here there is no good excuse for it being so terrible.)

Lamb Shank Casserole

Note: This entry has been restored from old archives.

Dinner's Up!

Hiding under all the soupy goodness is a shank!

While strolling back from Cinnamon Square (the best place in Rickmansworth for a ristretto) last weekend Kathlene and I wandered into the local butcher in hope that this time they would have some Osso Buco – no luck. However I did see some juicy looking lamb shanks, so they became dinner.

Ingredients:

  • Juicy Lamb Shanks
  • 500g Green Lentils (dry)
  • 2 ~400g Tinned Tomato
  • “Sufficient” Chicken Stock
  • 1 Cup White Wine (Sav Blanc)
  • Flour (just for coating lamb)
  • 5 Anchovies
  • 4 Generous Sprigs of Thyme
  • 3 Sprigs of Sage
  • 1 Cinnamon Stick
  • 3 Bay Leaves
  • 3 Red Onions
  • 2 Sticks of Celery
  • 2 tsp Chilli Powder
  • 2-3rds cup of Peas (defrosted if using frozen ones)
  • 100g Pancetta, thin sliced.
  • 1 tbsp plain flour mixed into 3 tbsp water
  • 1 Small Pumpkin (15cm diameter)
  • 2 Small Kumara (10cm long)
  • 6 Spring Onions

Coat the lamb shanks in flour and place in heated oil to brown, turning regularly; use a casserole large enough for the shanks to be fully covered with liquid Meanwhile slice up the celery, dice two of the onions, chop the spring onions and cut the pancetta into 1cm strips. When the lamb shanks are evenly browned put the onions, celery, pancetta and anchovies into the casserole and cook until the onion starts to caramelise. At this point throw in the chilli powder, cinnamon stick, bay leaves, thyme, sage and spring onions followed by the wine. Then tip in the two cans of chopped tomato and fill with stock until the lamb shanks are covered (if your shanks are as large as mine this will be quite a lot of stock!). Keep on high heat until the liquid starts to boil then reduce to a simmer and cover.

Meanwhile rinse the green lentils and put into boiling water for 10 minutes, scooping off any froth that forms. Once the ten minutes has elapsed tip into a strainer to drain.

After the lamb shanks have been simmering for 30 minutes add the lentils to the casserole, mix through and replace the lid.

Cut the pumpkin in half, scoop out the seeds then cut into 1 inch bands. Cut the skin off the pumpkin bands then cut into pieces that are very roughly 1 inch cubed in volume. Peel the kumara and slice into pieces about half an inch thick. Cut the remaining onion into large pieces (half, half, thirds).

After the casserole has simmered for another 30 minutes add the kumara and onion pieces. Let simmer for another 15 minutes then add the peas and pumpkin pieces. After a further 15 minutes drizzle in the flour mix while stirring and continue to agitate as the liquid thickens a little – after about 5 minutes turn off the heat.

Move the shanks to appropriate bowls, then remove any remains of thyme and sage sprigs from the soup (just stems and attached leaves) and the bay leaves; you could also remove the cinnamon stick at this point too but I prefer to break it up a bit and mix it through the soup as it should easily be soft enough to chew (yum!). Generously spoon the soup mixture and vegetables over the lamb shanks. Garnish as desired and serve with a good glass of dry red wine!

Soup

Soup

Leftovers

Leftovers

You’ll probably have soup left over, this is great to store and eat later. As we have a really huge casserole and only did two quite large lamb shanks we had a lot of left over soup – we had eight servings worth left! There’s still four in the freezer. It should be fine frozen for quite a while (we’ll finish it off this week though).

LinkSys WAG54GS Is Crap

Note: This entry has been restored from old archives.

[Update 2007-03-19: LinkSys have finally released an official firmware update for the WAG54GS! It is available from the LinkSys site. The lying buggers have it dated “12/05/2005″. I have not had the opportunity to install the firmware and see if it makes the WAG54GS less crap!]

I’ve traditionally been a fan of LinkSys routers, especially those distinctive blue ones with devil-horn wireless antennae. But I must say, the WAG54GS Wireless-G ADSL Gateway has proven to be a little turd of a device.

I bought it when I got to the UK, it has the latest official firmware, it regularly (several times a day) stops routing packets. It really is quite remarkable that such a total piece of shite could have made it through QA. It just stops, the lights stop flashing (but all stay on), the web interface doesn’t respond, it usually wont even respond to pings when this happens (although sometimes it does).

I’ve read vague reports from others on the ‘net regarding similar behaviour so this doesn’t seem to be an isolated occurrence. There is talk of a “better firmware” that can be built from source; the little fecal box runs Linux apparently (just confirmed that, there are instructions for getting a shell prompt on the box out there). But roll-your-own firmware is just too much piss-farting around for a device that should “just work”, if I wanted that I’d have bought a dumb ADSL modem and a mini-itx machine for Linux! Some forums indicate that an unreleased firmware version (1.00.08) is available for download, maybe I’ll give that a go (but a post on that same forum says that 1.00.08 was a problem and 1.00.06 worked better). What I wonder is: if this “better” firmware has been around for so long why is the severely broken 1.00.06 version still the latest official one! Surely any bugfix is worth releasing properly; I suspect the unreleased version is unreleased for a reason.

The OpenLinksys site seems promising – but the lack of English is a bit of a barrier for me.

All in all my conclusion is that the WAG54GS is excremental in nature and it appears that LinkSys are in no hurry to do anything about it.

My recommendation: Don’t buy it! If it is from LinkSys and isn’t a little blue devil-horn box it isn’t worth the risk.

Note: To get a shell on the thing:

  • Hit http://192.168.1.1/setup.cgi?todo=debug
  • And telnet 192.168.1.1

Where ’192.168.1.1′ is the IP address of your WAG54GS. Everyone seems to think the ‘adslctl info –stats‘ command is exciting. I’ll leave that one to the ADSL geeks – I’d just like the bloody thing to do its job!

Oh, it also has really shitty wireless range – another area where it is significantly defective when compared to the devil-horn versions.

Finally, some interesting stats from the device (with 1.00.06 firmware):

Linux Kernel: 2.6.8.1
"OS": BusyBox
Flash Size: 4096k
CPU: Broadcom BCM6348 V0.7 (bogomips: 253.44)
Memory: 13652 kB
Filesystem: cramfs
Interfaces: eth0, lo, ppp0, wl0, br0 (bridging eth0 and wl0)
Interesting Processes: 
 mini_httpd - The link is "I'm feeling lucky"
 udhcpd
 ntp
 crond
 scfgmgr
 atm_monitor
 cmd_agent_ap
 pb_ap
 wizd
 ses_update
 Pppd
 upnpd
 reaim
 utelnetd (presumably not normal)
iptables highlights (the full set is *large*):
--------------------------------------------
Chain INPUT (policy DROP)
target     prot opt source   destination
DROP       tcp  --  anywhere anywhere state NEW tcp flags:!SYN,RST,ACK/SYN
ACCEPT     all  --  anywhere anywhere state RELATED,ESTABLISHED
REAIM_IN   all  --  anywhere anywhere
INPUT_UDP  udp  --  anywhere anywhere
INPUT_TCP  tcp  --  anywhere anywhere
DOS        icmp --  anywhere anywhere icmp echo-request
ACCEPT     all  --  anywhere anywhere state NEW
--------------------------------------------
Chain DOS (6 references)
target  prot opt source   destination
RETURN  tcp  --  anywhere anywhere limit: avg 60/sec burst 120 tcp flags:SYN,RST,ACK/SYN
RETURN  udp  --  anywhere anywhere limit: avg 60/sec burst 120
RETURN  icmp --  anywhere anywhere icmp echo-request limit: avg 60/sec burst 120
LOG     all  --  anywhere anywhere limit: avg 10/sec burst 5 LOG level warning prefix `[Firewal l Log-DOS] '
DROP    all  --  anywhere anywhere
--------------------------------------------
Chain SCAN (2 references)
target prot opt source   destination
LOG    all  --  anywhere anywhere limit: avg 10/sec burst 5 LOG level warning prefix `[Firewal l Log-PORT SCAN]'
DROP   all  --  anywhere anywhere
--------------------------------------------
Chain DNS (1 references) (in nat)
target prot opt source   destination
DNAT   all  --  anywhere 192.168.1.1 random 50% to:213.208.106.213
DNAT   all  --  anywhere 192.168.1.1 to:213.208.106.212
--------------------------------------------

What a strange way to deal with DNS, it hands out its own IP address via DHCP but why not just hand out the external DNS IPs?