Runcible Blog

support your local business

guitar


Today I bought a guitar from Sandy's Music across the street. I had been meaning to check the place out since I've lived in the area, but I hadn't gotten around to it until now. It's a pretty neat store, and Sandy seems like a cool guy with lots of stories. Because I'm a terrible guitarist who just wants to noodle around, I looked for the cheapest acoustic I could get. I ended up buying the second cheapest guitar, which was covered with dust, smells like cigarettes, and sounds somewhat lousy. But I like it.

While I was in there, Sandy was talking to another customer about business (or the lack thereof). He mentioned that Beck and other members of his band once bought guitars there. Well, that just about sealed the deal for me! If Sandy's is good enough for Beck, it's good enough for me!

I'll never be as talented or as cool as Beck, but here's a cover nonetheless:

Golden Age



(untitled 11/2007)

I know nothing of love
that blossoms in Autumn,
with Nature-defying ease.

It grows through bold innocence,
unaware of the time or the timing or the timers.
It reaches and sprouts,
draws warmth from the tundra,
and thrives.

Who can smell the petals as the roots flourish underground?
While I long for this unknown wonder,
it whispers from the dirt,
"be patient"


this one's more recent, relevant, and romantic (to me, anyway)


Coping With Loss

 

Or, how to lose 5 pounds in one week...

Everybody handles loss and pain in different ways. I'm still trying to figure out how I should best handle these situations, but the approach I've taken in the past week has teetered between an introspective confusion and near-meltdown.

Through a series of unfortunate circumstances mostly (entirely?) out of my control, I lost a great friend and companion for the foreseeable future and possibly forever. I've spent the last week cycling through a gamut of emotions: sadness, anger, longing, shock, bewilderment, forgiveness, happiness (when we last met to talk), and loss again. Christmas eve was the worst: faced with the obligation of a family gathering, I almost shut-down completely. At times I couldn't muster the energy to open my mouth to talk to anyone. On Christmas I fared a little better, trying to distract myself with puzzles to avoid having to talk about what happened. I was neither festive nor present.

The rest of the week feels blurry now. Most of the time, I felt confused about what had happened and tried to search myself for answers, even though I knew the answers were out of my grasp. I haven't taken much care of myself or my apartment (even less than usual, believe it or not). I've forgotten to eat and surely lost weight -- less than 5 pounds, I hope (I can't spare too many). I've tried to make some pictures, and nature seemed obliged to reflect my mood. When I have wandered around outside, it's been in search of food. I caught the new screening of Blade Runner but can barely remember it. It seems my memories "will be lost in time, like tears in rain."

Sure, it hasn't been all bad. I played some pool with Nate, Sarah, and Sarah's friend on Sunday, and at some point I rented a heartwarming and depressing film (old people near death always get to me). Nate got me a Holga for Christmas, which I haven't really used because I've stayed indoors, which isn't conducive for Holga photography.

Right now whatever good experiences I've had seem like tiny blips on the radar compared to the swirling muddle of negative emotions and the looming feeling that I won't see my buddy again. Compounding the feeling of loss is a phenomenon that I tried to explain to Katie: increasingly, I feel like my memories are tied tightly to the visual record of the experiences I've had. If I haven't photographed it, I'm afraid the memory will fade completely, but if I have a record of an event, I can go back and drag the memories from the quicksand in my brain. I know the feeling is a little irrational (at least until I'm a bit older), but the fear of forgetting the good times makes me regret not documenting the time well enough, and I scramble to recall everything that's happened. Then I feel worse when I realize I can't go back and document something I didn't bother to record in the first place, leaving me with a dull anxiety constantly tugging on the back of my mind.

If there's any point to this post, it's that I don't have many answers and I don't really know what to do when I'm hurt. Staring out into the Charles River the other night, the emotional torrent and my trademark impetuousness briefly held hands before logic brought me back to my senses: I can't swim. The water must be cold. What will happen to my camera? It's not worth it. Go home. I delve inward at the same time as I try to let my feelings out in the open (witness this text). There must be some combination of introspection and expression that helps in these situations; I do know that distraction definitely doesn't work for me. It feels like a trick, and I don't want to trick myself. My brain deserves better.

I'm going to steal some of Warren Schmidt's words to Ndugu:

I'm not going to lie to you, Ndugu, it's been a rough few weeks, and I've been pretty broken up from time to time. I miss her. I miss my [Strüdel]. I guess I just didn't know how lucky I was to have a [partner] like [Katie] until she was gone. Remember that, young man. You've got to appreciate what you have, while you still have it.

Warren never really recovers from his loss. I think I will, but it doesn't feel likely right now. I suppose it never does at first.


Is exception handling slow?

Ned's post about "human sorting" lists lead to the inevitable comments from people who want to write the most succinct solution to the problem. Among them was the remark that "exception handling is slow." Ned asked me why it was assumed that exception handling was so slow, and I replied that it isn't (based on some of the remarks about improvements in exception handling in Python 2.5). I had no real evidence of the overhead from catching exceptions, so I thought I'd benchmark the different sorting methods

First, Ned's:

def tryint(s):
    try:
        return int(s)
    except:
        return s

def ak1(s):
    return [ tryint(c) for c in re.split('([0-9]+)', s) ]

Then, using str.isdigit instead:

def safeint(s):
    if s.isdigit():
        return int(s)
    else:
        return s

def ak2(s):
    return [ safeint(c) for c in re.split('([0-9]+)', s) ]

Somebody mentioned the new syntax in 2.5 that allows one-liner conditionals, thus saving a function call:

def ak3(s):
    return [ int(c) if c.isdigit() else c for c in re.split('([0-9]+)', s) ]

Of course, there's the easy optimization of compiling the regular expression beforehand:

NUM_RE = re.compile('([0-9]+)')
def ak4(s):
    return [ int(c) if c.isdigit() else c for c in NUM_RE.split(s) ]

Ok, so what were the results? Here, I'm sorting a 5000 item list of strings created like so:

def make_list(sise): 
    samp = string.letters + string.digits
    return [''.join(random.sample(samp, 4)) for i in xrange(size)]
for each function:
timeit.py -s "import sorting; td=sorting.make_list(5000)" "td.sort(key=sorting.ak1)"
Results:
ak1: 80.7 msec
ak2: 37 msec
ak3: 34 msec
ak4: 18.1 msec

It turns out the conventional wisdom isn't just an old pythonic wive's tale: exception handling is slow. Even though ak1 would've been my first thought for the function (hanging around with Ned too much?) because it seems more pythonic to just try to convert the value to an int and catch the exception if it's not an integer, that function is 4 times slower than the fastest case. Also, this benchmark shows that there isn't much of a gain from the new conditional syntax, even though a function call is saved.

As usual, pre-compiling the regex makes lots of sense for performance-critical code. For giggles, I have a function (that I suppose works...) which avoids the regular expression:

def ak5(s):
    new_s = []
    b = ''
    for c in s:
        oc = ord(c)
        if oc > 57 or oc < 48:
            if b:
                new_s.append(int(b))
                b = ''
            new_s.append(c)
        else:
            b += c
    return new_s

It's not as slow as I thought, averaging 25.5 msecs on my machine.

What have we learned today?

  • Python exception handling isn't nearly as lightweight as I thought. Especially avoid it in tight loops.
  • Function calls should be minimized. (duh)
  • Sometimes the more succinct solution isn't faster.
  • Compile common regular expressions. (duh)