AI: An Interesting Day
The plan for today was to write about Turing and intelligence. People misunderstand Turing and his test because they assume that Turing, being a mathematician and engineer, knew nothing about “intelligence”. That’s wrong. But it’s for another day.
Among other tasks today, I had a user report of poor performance in the Tinderbox attribute browser. The user’s document is about 3,500 notes, which used to be a really big document, and so performance issues aren’t a surprise. In the presence of attribute and rules, the Attribute Browser must consider every note, perhaps every three seconds. If there are lots of notes, that might be a problem.
I used the profiler to verify that this was, in fact, a bottleneck. A key step is that, before you can decide the categories of the Attribute Browser, you’ve got to know what values the attribute takes on. That means looking at every note. This took perhaps 25% of the available time and blocked the main and the agent threads. Could it be faster?
I asked Claude, “here’s how we do things now. Could we do this in parallel?” Claude replied that “Yes! It certainly would be faster in parallel. But remember: I have a note about a complete bollix we had with lazy evaluation in dispatch_apply in another chat last week. We don’t want to do that again!” This was the first concrete success for Claude’s note taking.
So, Claude proposed a fairly standard approach using a `dispatch_group`: set a bunch of processes working on separate parts of the document, wait for them all to finish, then merge the results. It wasn’t a pretty method, but OK: it worked, and cleaned out about 20% of the workload.
I’d tweaked Claude’s proposal en passant because it really wasn’t written in my style, but even so, this was ugly. So I refactored to a method object, and then did a bunch of extract methods and extract instance variable to clean things up. At this point, I sent it all back to Claude, hoping that Claude would get some style hints. Instead it pointed out a race condition in my code. (It was also a race condition in Claude’s code, but this isn’t a competition.) So, we got rid of that.
At this point, we’re fast. I’ve made the point to Claude (I hope) that casts are a code smell and that storing naked pointers in NSValue wrappers is really unsightly. The result is reasonable code, code that is very much mine, but Claude really did help out.