Category Archives: Comedy

Good-bye App Engine

I’d been running my web site for comedians LaffQ.com in Google App Engine for nearly two years. Google App Engine seemed pretty neat when it first came out: it was the only free hosting service I knew of where you could deploy dynamic Python apps (using Django no less, a framework I was already familiar with) with the promise of Google managing the backups, scaling, and provisioning.

But as time went on, the sunny optimism began to fade. Although Google supported Django, it uses a proprietary BigTable-backed database which was not compatible with Django’s object-relational wrapper (ORM). The originally unbelievably high free limits during the beta period which reduced drastically, in some cases absurdly, when the product came out of beta. Visiting my internal operations page just twice could blow out nearly the entire day’s quota because it produced counts of many tables — so each item counted towards a daily quota of 50000 “small operations”.

Developing for Google App Engine was always a pain. It was non-standard enough that a lot of libraries and tools wouldn’t work or need annoying changes. There was a single point of documentation, written in a sort of corporate Google-ese — not horrible, but not the nicest documentation I ever read. There were a lot of layers of abstraction. It was proprietary. It was slow to fetch data. The pdb debugger didn’t work very well. Getting data out of production was an ordeal. It was even hard to launch a instance on the command line, which meant on those rare occasions when I decided to do development on my Linux netbook, I spent most of my time getting the newest version of Google App Engine to work again.

I don’t exactly remember how or why, but late one Sunday evening in November I suddenly came up with the bright idea to port the Google App Engine infrastructure to “sqlite” (as I referred to it in my head), ie. to use the standard Django database back-end with the idea to deploy it to some unknown host using sqlite3. I started almost immediately, figuring at the very worst, it would just be an abandoned experiment.

It turned out to be… well, if not “surprisingly easy”, remarkably painless. By Monday afternoon, I had gotten most of the core public functionality working just fine (insert show, edit show, delete show, list shows). The data model ported straight across with, one exception being a GeoPt latitude/longitude structure, which I simply reformatted into a string containing a comma-separated pair (which is was probably stored as in Google anyway).

By 9 pm on Monday, my entire test suite was passing. The internal pages hadn’t been ported yet, nor the “post on Facebook” functionality.

I decided to work on the non-critical internal pages first, or else I wouldn’t have any excuse to not deploy (and that’s scary!). I ported these components which gave the code base a chance to “set” (like Jello™) and time for that unease associated with massive changes to dissipate somewhat.

Some changes that occurred more than once:

– adding “objects” everywhere, so Model.get becomes Model.objects.get
– changing Property to Field (ndb.StringProperty => models.CharField for example)
ndb.KeyProperty => models.ForeignKey
put => save
key.get. => key.
.query() => .objects
required=False => null=True
obj.key.delete() => obj.delete()
query.order => query.order_by
query.filter works very differently (no more fancy Google App Engine custom types based on operator overloading and deferred evaluation… fancy, but pretty opaque)

On Tuesday, I started working on the automated posts to Facebook. Not much needed to change here, but it was a bit nasty as there were only limited automated tests for this, so I had to be very cautious. Somewhere along the line, I decided I would deploy on my unlimited Dreamhost account (promo code: “RICHARD_SHARES”), which costs about $9/month and already hosts a bunch of domains. There were a few gotchas in getting the wsgi configuration working with Django (and it was tremendously difficult to debug until I hit on this idea of marshaling the requests to a file, then invoking the server by hand using the marshaled request), but this was reasonably straightforward, and I had built a local installation of Python 2.7 in the past, so I reused that.

I worked on the code to import the data. Google Data Export is another things that’s way too complex and slow, but I had done a trial run of the export on Sunday, so I used that as a testbed. I found some sample code to read the sqlite database (which is very simple) into Google Entity objects, so it was fairly simple to read properties out of the Google objects and put them into Django objects. I ended up doing it in two passes; the first pass included root objects that other objects have foreign keys to, which ensures that the second pass can refer to those already created objects without dangling foreign keys.

I waited until midnight, so the daily stats would be generated on Google, with Google data, then immediately put the site into read-only mode on Google and began the dump of data from Google. It was infuriatingly slow. It finally finished around 12:42 am, so about 40 minutes total, to produce a 21 MB sqlite database file. Finally, one little file with ALL my LaffQ data in it!

Here’s the script that converted the exported Google App Engine data to native Django objects in sqlite3: https://gist.github.com/richardkiss/4576523

I had already brought up the new site on Dreamhost, using two day old data, so it was just a matter of running the conversion tool, which read the Google sqlite database (which was essentially a BigTable dump, with one entity) and wrote out the Django sqlite database (which much more closely resembled the actual structure of data in my database). The new sqlite file was 8.7 MB. Compressed with bzip2, it was under 2 MB. That was the entirety of my web site data that took Google 40 minutes to export!!!

I copied it to Dreamhost in about five seconds, deployed it, restarted the Django app, and poked around a bit. Everything seemed to be in order and up to date, so I update DNS to point to the Dreamhost version of the web site, and waited for the change to propagate around the world (it’s funny to think about how LaffQ came up at different times for different people).

One thing I forgot is the Facebook integration required SSL. I didn’t have an SSL certificate (or a unique IP!) so I was flustered for a bit. I thought about how this used to work: it went to the laffq.appspot.com domain, the Google domain that supports SSL for free (signed with a Google appspot.com SSL certificate). Then I realized, I could just write a tiny Google App Engine app that proxied requests to https://laffq.appspot.com/ by fetching content from laffq.com. These pages are very low traffic (since they don’t really do anything), and it worked! (I had problems serving CSS to Chrome, which were resolved by making sure the content-type header was set correctly).

I’m kind of glad I didn’t remember this until it was deployed because I didn’t see the answer right away, and it might have made me not go through with it due to my tendency to know every move in advance.

All in all, the port went unbelievably well. The sqlite version is MUCH faster than Google even though memcache is no longer in the mix (I do use built-in Django caching in the same memory space as the Django app, although I’m pretty sure I could turn it off and it would still be very fast). It uses very little CPU on Dreamhost, and there are no annoyingly arbitrary quotas.

Since then, my work on LaffQ has accelerated beyond my wildest dreams. I didn’t realize just how much the Google App Engine restrictions were holding me back. Now I can back up my entire production database in just a few seconds. I can run a copy of production database locally, which gives me a much better feel for how changes will perform with production data, so I use production data in development all the time. This gives me a much better feeling about new features. Debugging is much easier. Deploying is as simple as a git push/git pull. I can look at logs. I can make tweaks in production. I can ssh to the production machine. I can diagnose problems in production. Pretty much everything about it is better. I’ve refactored, tweaked, optimized, added tests. It’s code I’m almost proud of now. (Almost.)

I saw on Hacker News the other day about how Google App Engine was down. I was happy it didn’t affect me.

People Get Better at Stuff

I’ve been doing stand-up comedy for four and a half years now, and done over 400 shows. Recently, I taped a longer set I’ve done and posted it on my web site. I’m happy to see that I’m improving (I’m assuming. I haven’t actually watched it yet). I did 18 minutes, and while not 100% solid and consistent, it’s definitely tolerable, if not funny. I’m hopefully overcoming my biggest weakness of being too boring and monotone with some fake excitement, inflection and movement.

Audiences should realize, however that comedians get better. When you go see a comic live, you aren’t seeing a movie. You’re seeing a slice of a comic’s life. Their performance, although possibly rehearsed, is just another rehearsal, another practice for the shows that comes after. It’s not a final product. It’s another attempt, another try at improving, being funnier, becoming more compelling, getting more interesting. You’re just a guinea pig in this somewhat scientific experiment, and your reaction – laughter, groans, silence, obedience – is the feedback.

Just because a comic is not funny or has a bad show does not mean you will never like that comic. It’s pretty amazing how much I’ve learned and changed in just the last two years. Talent plays a role, but comedy, like pretty much anything else, is something you get better at with practice. When you go see a comedian, you’re watching him or her practice. Just by being there, you’re helping comedians get better.

Thanks, audience member. Here’s your gold star.

Click to Make My Ears Burn

When I was on Guy MacPhereson’s “What’s So Funny?” radio show, off air he mentioned to me that he had a short discussion with Irwin Barker about one of my jokes on air in a prior episode. Well, Guy emailed me last week to tell me that the episode was going to re-air, so I listened to it.

Here’s the excerpt (2 minutes, 32 seconds):

(Click here if you don’t see any way to play the audio above or if for some crazy reason, you want to download it.)

Here’s the joke he’s talking about, from the night he saw me (70 seconds):

(Ditto)

I continue to maintain, the only thing worse than being talked about… is not being talked about.

Adding Ten Pounds

I’ve had a video camera pointed at me a fair bit in the past week.

My comedy friends Chris Schiacappasse (she-ack-uh-PASS-ee) and Vahé Hovak have a recurring YouTube show called “Hanging Out” where they come over and for some unscripted hang out. A genuine reality show.

In our episode, after seeing a TV commercial for some 99¢ fast food hamburger, we decided we would hit a handful of fast food joints, buy one burger-thing that costs a dollar from each, then take them home to sample and compare them.

We hit McDonald’s, KFC/Taco Bell (two purchases from each substore there), Wendy’s, Jack-in-the-Box and Burger King. We also stopped at Arby’s and Carl’s Junior, but neither of those snooty establishments had any burgers that met our thrift constraints.

My surprise favourite was Jack-in-the-Box’s Junior Cheeseburger, which despite looking like it had been run over by a truck and not really tasting like actual food, had a wonderful salty delicious flavour of chemical that made me crave more.

Unfortunately, various technical problems (a low battery, then we ran out of tape) means that large portions of this part of the taste test were not taped, so this info probably doesn’t qualify as a spoiler.

This episode will be probably be available on YouTube eventually. In the future.

Then, last night I went to the monthly taping of “Paint with Lynn”, a show on public access cable TV channel 26 in Pacifica, California, where host Lynn Ruth Miller, a near-octogenarian comedian, painter and ne’er-do-well comes up with an art project.

I haven’t done an art project since elementary school. We worked on our projects separately while trading quips. It was a blast and I’m simultaneously curious about and dreading the final cut. If you have access to Pacifica cable, “check your local listings”. I’ll be getting a DVD (also in the future) which maybe I can post on the internet.

The Curse of Originality

I’ve been trying very hard to produce tangible output on a regular basis for my blog. But it’s been challenging. I worry about being interesting, but only a bit, because the “interesting” angle is so much outweighed by my innate need to be original.

Ah, the curse of originality, or as comedians like to say, “not hack”. I strive to be a brilliant computer hacker while I strive to avoid being a comedy hack. Hack computers, not comedy.

Upon reflection, this desire – this need – to be original has been a constant driver in my life. I’ve always felt different, and always felt the need to be think about things differently. When everyone else zigs, I zag. I don’t know why. It’s in my nature. I can’t help it any more than the scorpion can help but sting the frog.

My blog and my comedy suffers because I so quickly and naturally filter out ideas that seem obvious and unoriginal automatically. They’re considered, but only considered as ideas that have been seen and noted, and never considered to be used on stage or in public. A lot of times, I’ll even dismiss as unoriginal ideas that I’ve come up with myself, but in the past, so they are unoriginal in that “I’ve thought of them before”.

I suppose this blog post is personal enough that it’s guaranteed to be original. Even if someone else has written these exact ideas, or even somehow these exact words, I’m still original because they (probably) weren’t writing about me. Maybe that’s the answer: write about myself.

SEEN IT

Huh. I guess that’s been done. To death.

27 Random Questions

From a MySpace bulletin, circa 2007. The author of the questions is unknown but all answers are by me.

1. When you looked at yourself in the mirror today, what was the first thing you thought?
“WHERE DID I PUT MY LEFT EYE?” SOUND WEIRD BUT TO BE FAIR I WAS TOTALLY HIGH

2. How much cash do you have on you?
ALL OF IT

3. What’s a word that rhymes with “DOOR?”
“NATURES”

4. Favorite planet?
I WOULD SAY URANUS BUT IT’S TOO FILTHY SO I WILL GO WITH OMICRON 7 IN THE ANDROMEDA GALAXY. EVEN THOUGH IT’S GASEOUS, IT ROCKS!!!

5. Who is the 4th person on your missed call list on your cell phone?
CREDITORS

6. What is your favorite ring on your phone?
RING AROUND THE COLLAR HA HA HA I KILL ME. THINK OUTSIDE THE BOX PEOPLES!

7. What shirt are you wearing?
WHAT IS THIS, PHONE SEX?

8. Do you “label” yourself?
YES I DO. CONSTANTLY. LOOK I’M DOING IT NOW

9. Name the brand of your shoes you’re currently wearing?
I WILL NAME IT JEREMY AND THANK YOU FOR ASKING! YOU ARE A TRUE FRIEND

10. Bright or Dark Room?
IT DEPENDS ON IF I AM DEVELOPING PHOTOS

11. What do you think about the person who took this survey before you?
I THINK ABOUT 145 POUNDS

13. What were you doing at midnight last night?
IT WAS NOT MIDNIGHT, IT WAS ABOUT 11:30 AND IT WAS NOTHING.

14. What did your last text message you received on your cell say?
SENDER UNKNOWN, REDO FROM START

15. Where is your nearest 7-11?
THE CORNER OF 7TH STREET AND 11TH AVENUE. I KNOW. WHO WOULDDA GUESS?!

16. What’s a word that you say a lot?
“I” BECAUSE I AM VERY IMPORTANT TO I. GET IT?

17.Who told you he/she loved you last?
HITLER LOVED ME LAST AND HE WAS VERY CLEAR ABOUT IT

18. Last furry thing you touched?
HA HA THIS ONE IS TOO PERSONAL TO ANSWER BUT I WILL GIVE YOU A HINT… IT HAD A PIT BUT WAS NOT A PEACH!!!!!

19. How many drugs have you done in the last three days?
JUST ONE WHEN YESTERDAY I INVENTED A MEDICATION TO LOWER BAD CHOLESTERAL BUT THE DAMN PATENT OFFICE REFUSED MY PATENT!!!! BASTARDS LOL

20. How many rolls of film do you need developed?
I WILL ANSWER THIS FOR EVERYONE SIMULTANEOUSLY: N WHERE N IS A NON-NEGATIVE INTEGER

21. Favorite age you have been so far?
ICE AGE WAS MY FAVOURITE BECAUSE THAT LITTLE SQUIRREL SO CUTE

22. Your worst enemy?
JEWS

23. What is your current desktop picture?
IT IS A PHOTO MY PREVIOUS DESKTOP. I KNOW, BLOWS THE MIND, EH?

24. What was the last thing you said to someone?
“IT IS A PHOTO MY PREVIOUS DESKTOP. I KNOW, BLOWS THE MIND, EH?”

25. If you had to choose between a million bucks or to be able to fly what would it be?
I WOULD CHOOSE DOOR #3 WITH THE GOAT IN IT AND THEN SLAUGHTER IT TO GAIN ITS COURAGE

26. Do you like someone?
YES BUT NOT A PEACH!!!! *WINK*

27. The last song you listened to?
MY OUTGOING VOICE MAIL MESSAGE WHICH IS SUPER CATCHY. CALL ME AND GET YOUR GROOVE BACK