« May 2007 | Main | July 2007 »

June 2007 Archives

June 5, 2007

On Resource Pressure

A quick one for today, sparked by recent events at work. It can pretty much be summed up in this even quicker question: do you know what your program does when it's out of resources? Out of RAM, out of disk-space, out of address-space, out of time? Computers are indeed powerful beasts these days, and there's a bunch of people who would like you to believe that they are effectively infinitely powerful, but observing your code working with limited resources, even if those limitations are artificially imposed, can tell you a lot of things you mightn't have known previously. I promised you this one would be short, so without further ado, here's my grab bag of stuff you should check for:

What happens when your program writes (or reads) a file greater than 2GB? 2GB is a magical number, and you might have good reason to believe that your program just won't ever have to deal with that much data. But can it? The time you want to find out is in the comfort of your office, running your code in the debugger. I made the unfortunate discovery this Sunday (!) that a popular open-source IPS tool segfaults in this sitution. Not cool. It's ok for your program to be unable to deal with large files, but segfaulting is not the answer. Open another file, throw an error, whatever. Just don't segfault!

What happens when you run out of disk space? The guarantee you want to give your users is that you might lose work since the last check-point, but nothing more than that. Can your program start when there is no disk space at all? An answer of "no" is ok on this one, but make sure you've got a good error message if that's the case.

What happens when malloc() actually does return NULL? This is one of those things that falls under the heading of building testing into your code. Abuse LD_PRELOAD to build a malloc replacement that fails randomly 1 in 100 times and run your program at full load. Does it operate at 99% of its previous performance level, or does it crash? Does it run?

What if you're just plain outta RAM? Write a program which, every 20 seconds, allocates a megabyte of memory, and run it in parallel with your code. You'll need to actually paint that memory, because Linux (and likely other OSes) have a feature called over-commit, which lets you ask for more memory than the system actually has. It is only allocated when you actually use it. Granted, sooner or later you'll trigger the OOM killer, but memory pressure has a bunch of manifestations that'll turn up long before then. Running with less RAM is also a good way to find memory leaks faster -- they manifest as crashers much sooner when there's less RAM.

Out of lock-slices? -- ok, so I don't know if "lock slices" is part of the common engineering lexicon, but they're the random discrete unit of measurement I've adopted here to talk about lock contention. Basically, if you force your program into a situation where your locks are getting absolutely hammered, and you throw your hardest workload at the program, what happens?

I've espoused the virtues of static memory pools here before, but static pools hand back to you a concurrency problem that otherwise belongs to the memory allocator (or so everyone pretends) -- that of lock contention on memory acquisition and release. There's a bunch of pros and cons here that I won't go into, I'll only say this: if you do go with a static pool allocation system, build into your code the ability to configure the size of those pools, even if you never expose that configurability to your users. Then, you can (or rather, must), set these pools to an absurdly small number and hammer your code.

This strategy is 100% awesome in my opinion. We tried it today and it uncovered a deadlock in 10 seconds that a whole weekend of pushing packets had missed. Money just can't buy that kind of happiness.

I won't harp on this one too much longer, it's just one of those things you should try before you push out a release. It's also good to keep track of results between releases to guard against resource-creep. Understanding all the failure modes of your software is an absolute must if you expect to support it. Get this stuff right and that's a whole realm of problems you'll never have to explain to your customers. As they say in those oft-parodied Visa ads: priceless.

June 11, 2007

Online Lectures From UC Berkeley

Ultra quick entry for today to let you know about webcast.berkeley.edu where you can watch lectures given at UC Berkeley. If, like me, you'd just like to queue up downloads for the whole lot and watch them at your leisure, mplayer is the way to go. Fetch the file they link to from the webpage, it will contain a link that looks like this:

rtsp://169.229.131.16:554//classes/s2007/ee225b/20070117.rm?start=00:00:05&end=01:14:11

Which mplayer can view and, more importantly, dump out to disk. Like so:

mplayer -dumpstream 'rtsp://169.229.131.16:554//classes/s2007/ee225b/20070117.rm?start=00:00:05&end=01:14:11'

You'll get a stream.dump file with the lecture in it in RealMedia format. Alternatively specifying the '-dumpfile' argument lets you name the file.

University was altogether too short for me, so being able to watch a few more lectures is always a good thing. I'm currently making my way through the digital image processing course.

Here's my dodgy script to download all of that course:



#!/bin/sh

mplayer -dumpstream -dumpfile lecture-1.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17665')
mplayer -dumpstream -dumpfile lecture-2.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17666')
mplayer -dumpstream -dumpfile lecture-3.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17667')
mplayer -dumpstream -dumpfile lecture-4.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17668')
mplayer -dumpstream -dumpfile lecture-5.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17669')
mplayer -dumpstream -dumpfile lecture-6.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17670')
mplayer -dumpstream -dumpfile lecture-7.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17671')
mplayer -dumpstream -dumpfile lecture-8.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17672')
mplayer -dumpstream -dumpfile lecture-9.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17673')
mplayer -dumpstream -dumpfile lecture-10.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17674')
mplayer -dumpstream -dumpfile lecture-11.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17675')
mplayer -dumpstream -dumpfile lecture-12.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17676')
mplayer -dumpstream -dumpfile lecture-13.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17677')
mplayer -dumpstream -dumpfile lecture-14.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17678')
mplayer -dumpstream -dumpfile lecture-15.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17679')
mplayer -dumpstream -dumpfile lecture-16.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17680')
mplayer -dumpstream -dumpfile lecture-17.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17681')
mplayer -dumpstream -dumpfile lecture-18.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17682')
mplayer -dumpstream -dumpfile lecture-19.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17683')
mplayer -dumpstream -dumpfile lecture-20.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17684')
mplayer -dumpstream -dumpfile lecture-21.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17687')
mplayer -dumpstream -dumpfile lecture-22.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17689')
mplayer -dumpstream -dumpfile lecture-23.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17690')
mplayer -dumpstream -dumpfile lecture-24.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17691')
mplayer -dumpstream -dumpfile lecture-25.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17692')
mplayer -dumpstream -dumpfile lecture-26.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17693')
mplayer -dumpstream -dumpfile lecture-27.rm $(wget -o/dev/null -O/dev/stdout 'http://webcast.berkeley.edu/stream.php?type=real&webcastid=17695')


Enjoy!

June 21, 2007

ctags and cscope

If you're a programmer, and you use the excellent vim editor, you really need to get into ctags (the 'exuberant-ctags' package on debian, not the normal 'ctags' one) and cscope. These are both awesome tools, but there's plenty of info on making effective use of these tools for your own builds (cscope info here, and ":help ctags" for ctags, or google around), I thought I'd share a couple of other tid-bits on how I use them which have improved my productivity.

The Alias

Pretty simple really, I throw this:

alias t='ctags -R; find . -name "*.c" -o -name "*.cc" -o -name "*.hpp" -o -name "*.hh" -o -name "*.h" -o -name "*.cpp" -o -name "*.py" -o -name "*.pl" -o -name "*.pm" | cscope -Rb -i-'

into my .bashrc, and run 't' whenever I need to update my tags and cscope files. The -i argument to cscope works around issues you'd otherwise have with the file list being too long.

System-header tags

This one is a bit more useful. Add this to your .vimrc:

set tags=./tags,./TAGS,tags,TAGS,/usr/include/tags

and then go off and run the body of that 't' alias in /usr/include (or do it from cron if you want it to stay up to date). That way when you're trying to remember which header file it is that defines, for example IPPROTO_TCP (I can never remember that one), you're not reduced to grep -r, and vim will tab-complete when you do the search, and even remind you which IPPROTO's there are. For example, I fire up my vim and type ":ts IPPR" and then press ctrl-d, I'm greeted with this:

:ts IPPR
IPPROTO_AH        IPPROTO_HOPOPTS   IPPROTO_MAX       IPPROTO_ROUTING
IPPROTO_COMP      IPPROTO_ICMP      IPPROTO_MTP       IPPROTO_RSVP
IPPROTO_DSTOPTS   IPPROTO_ICMPV6    IPPROTO_NONE      IPPROTO_SCTP
IPPROTO_EGP       IPPROTO_IDP       IPPROTO_OSPF      IPPROTO_TCP
IPPROTO_ENCAP     IPPROTO_IGMP      IPPROTO_OSPF_LSA  IPPROTO_TP
IPPROTO_ESP       IPPROTO_IP        IPPROTO_PIM       IPPROTO_UDP
IPPROTO_FRAGMENT  IPPROTO_IPIP      IPPROTO_PUP       IPPROTO_VRRP
IPPROTO_GRE       IPPROTO_IPV6      IPPROTO_RAW

I can keep typing, or press tab to complete the first one and hit enter, which then tells me this:

  # pri kind tag               file
  1 F   e    IPPROTO_AH        /usr/include/linux/in.h
               IPPROTO_AH = 51,             /* Authentication Header protocol                   */
  2 F   e    IPPROTO_AH        /usr/include/netinet/in.h
               IPPROTO_AH = 51,       /* authentication header.  */
  3 F   d    IPPROTO_AH        /usr/include/netinet/in.h

That is, I have definitions for that constant in netinet/in.h and linux/in.h -- for maximum portability you should use the netinet version, but that's a lot easier than other ways I can think of to get that info. It also works for structure definitions and function prototypes, and if you want to dive into the definition itself, hit the number on the left (I've bolded it) and press enter. Zap, you're there. ctrl-t to bounce back. I also keep a copy of the Linux kernel source code indexed with ctags and cscope for when I do kernel development, I only pull that in when I need it though, because it generates a lot of noise for userspace stuff.

Make the best use of the tools you have; sometimes they're a distraction but used well, they can be a huge productivity boost.

Got a favourite tool? mail me about it.

About June 2007

This page contains all entries posted to Code Lore in June 2007. They are listed from oldest to newest.

May 2007 is the previous archive.

July 2007 is the next archive.

Many more can be found on the main index page or by looking through the archives.

Powered by
Movable Type 3.35