MBP: Wash. Rinse. Repeat.

May 6th, 2006

This post is part of my MacBook Pro Complaints series. Instead of (or in addition to) linking directly to this post, consider linking to the series link, which includes a summary of all findings to date and direct links to the pertinent downloads that users may find useful. Thanks for reading!

I know everybody is sick of this issue. Believe me, I am too. But for the people following along from home I feel obligated to keep you posted on this until it reaches a resolution. Here is the latest chapter in my experience with getting my MacBook Pro repaired.

So far my machine has only been to AppleCare service once. I sent a long list of problems and hoped that at least some of them would be addressed. The machine came back largely unchanged, and now I’m trying to decide when and if to send it back. Most of the existing noise problems persist, and now that spring is descending on the Northeast with summer-like temperatures, the heat is more unbearable than ever. My hands literally get sweaty while typing on the thing! If that’s normal, then the world is due for a revision to laptop design. I bought the Apple argument that it’s “not a laptop.” But if it makes my palms boil there isn’t much I can do for that short of using an external keyboard.

I finally got up the psychic energy to call AppleCare back. It’s always hard to make these calls, because you have to steel yourself against the inevitability of them trying to convince you again that the problem isn’t really a problem. Yeah, OK. But anyway this time I got put pretty quickly in touch with a “product specialist” because my complaint was that a repair had come back with symptoms unfixed. To be honest, I was expecting most of the problems to be unfixed. But I didn’t expect the “display buzz” to still be there! That’s the one thing they had expressed confidence about fixing. I had agreed to send my machine in, and be without it for more than a week, so that I could at least get the display buzz fixed. I figured, if I had to suffer all the symptoms that everybody else does, at least I want to get the part that’s fixable fixed.

So now that Apple wasted a bunch of money on shipping and labor just to send me a machine nearly identical (except with the hard drive wiped) to what I’d sent them, I’m more than a bit hesitant to send it back off for another round of attempts.

To their credit, they claim that this time around it will go to a “higher level” of service. I guess that means somebody capable of actually repairing machines? I don’t know. It seems like it would have been worth it, sometime around when they were reformatting my hard drive, to also turn on the machine and see if the one symptom they were sure they could fix … was fixed. At least then I’d only be complaining about the CPU whine and the mooing. And I’d have a somewhat improved user experience (to be fair, they did manage to fix the “high pitched squeal” through some luck).

I’m pretty close to just accepting the flaws of the machine that may not be fixable. We may all be stuck with CPU whine and mooing. OK. If we’re all in this together, I think I can deal with it. I’m not happy about it, but I can deal with it. I’ll refine my QuietMBP application, embrace the udder cowness of my machine, and wear oven mitts or something while typing.

But I want the buzzing to go away! At least!

Now I’m faced with the prospect of going through all that “sending it in” garbage again, hopefully this time with a semi-joyful resolution at the end. But being without the MBP for that week and a half is damaging to my productivity. The very act of choosing a “least harmful time” to send it back in is stressful, and I’m liable to make the wrong choice, and end up wishing 4 days in that I had it available for Intel testing or portable use.

I’m going to think about it over the weekend and decide on Monday whether and when to send it in again.

Update: I meant to point out that there is a loose plan to do a launch a mass complaint against Apple in particular about the CPU whine problem. It tickles me pink to see any mobilization at all on the issue, so I am supporting the cause. But I don’t really care when you call, as long as you do call. One of the things that bothers me is that some people are running my software to workaround the whine, and therefore not complaining with Apple about the problem. I was guilty of this with the PowerMac G5 whining problem. I was just too busy and depended too much on my computer to let it out of my hands for a round of attempted repairs, so I never called.

If you have the whine and it bothers you, it’s imperative that you at least let Apple know once that the whine is bothering you and you want it fixed. If you’re not ready to send it in, at least call up and complain about the problem. Tell them you can’t send it in yet but you want to open a case for it and will think about when you can find time to send it in.

To encourage vocalization about the problem, I wonder if some kind of “I Whined” badge might be helpful? If there are any graphic artists reading this who would be interested in donating your time to whip up a quick graphical badge suitable for web display, let me know. If we can get people to place “I Whined” badges on their sites after calling Apple, then it might encourage others to do the same. I would also be willing to set up a page here dedicated in particular to the whine problem. Then users could have the badge point at that page for more information.

Just a thought. We can’t take this lying down (with our hands over our ears).

CoreGraphics Log Jam

May 5th, 2006

It’s been a while since I’ve complained about Apple in the context of an actual bug report, so here is a little diversion back into “Apple Bug Friday” land.

One of the aspects of Mac OS X programming that can really frustrate traditional Mac OS programmers is the lack of error reporting from many APIs. While traditional Carbon APIs tend to return numeric failure codes when something goes wrong, it’s not unusual for CoreFoundation and related APIs to simply return NULL. What’s the developer to do in this case? The usual argument is that NULL is returned only from functions where a more specific error would not help the programmer convey meaningful information to the user. In other words, if it returns NULL when you don’t expect it to, your computer is either melting down, or you’ve got some debugging to do. Regardless of the validity of this argument, it can be infuriating to look at code that seems perfectly correct, and be clueless as to why it is failing.

I was chatting with Jonathan Wight when he shared his frustration with the CGBitmapContextCreate function. He was in the midst of debugging just one of these mind-boggling NULL returns. All the parameters looked more or less correct but the function just plain refused to cooperate.

I guess I was between builds or something because I got interested in the problem. While Jon took the more efficient path of carefully examining the parameters being passed and comparing their values to the documentation’s restrictions, I started traipsing through assembly in Xcode. You know, the fun stuff.

Of course, Jon found the answer first. It was a problem with the combination of colorspace and alpha parameters. The limitations are well-documented (if a bit overwhelming) in Apple’s Technical Q&A. In this case, Jon was fetching the values directly from a CGImage that had been loaded from disk. Can’t blame a guy for thinking that maybe a JPG image’s attributes might be suitable for creating a bitmap context!

Even after the bug was resolved, I continued digging into the framework via the debugger. I’m due for a complete retraining on Intel, but as long as I have my PowerPC machine around, I’m fairly comfortable zipping through the various API to see what really happens when an error occurs.

Sure enough, a few levels into the API, I spot an examination of the input colorspace, and an objection to the fact that it was only 24-bits per pixel. Great, I thought. If the API knows exactly what’s wrong, why doesn’t it let us know somehow, at least through a logging message or something. Then I spotted a call to “CGPostError.” Well, that’s interesting. A well-defined error reporting mechanism? The results of which the developer never sees? I traced along a while until discovered myself in a logging function, the parameter to which was this choice bit of text:

CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component;
	24 bits/pixel; 3-component colorspace; kCGImageAlphaNone.

Well! It doesn’t exactly point to the right solution, but it would have been nice to know! Thanks for not sharing, CoreGraphics. Why the heck does it go to all this work and not print out the result? I decided to dig deeper.

The framework has an internal function, “hasTerminal,” which seems to control whether logging to the console occurs or not. I guess the engineers on the CoreGraphics team are trying to be considerate and not spew logging messages all over your console log unless you’re actually, you know, debugging. Here’s the kicker – hasTerminal returns true if you are running from the terminal. All Jon had to do was test his app from the command-line and the exceedingly helpful logging message would have appeared.

But the “hasTerminal” function returns false when debugging from within Xcode. Bugger that debugger! How does hasTerminal decide whether to allow logging or not? It simply attempts to open “/dev/tty” with read/write access. If it is successful, the user must be running from a terminal? But somehow, when running from within Xcode, this test fails, and therefore logging is not done. I assume this has something to do with Xcode’s magic terminal-esque window, but the discovery raises two questions:

  1. Should CoreGraphics limit its logging functionality based on assumptions about “/dev/tty”?
  2. Should debugging in Xcode impact a target application’s ability to open “/dev/tty”?

These questions are posed in Radar #4538344– “CoreGraphics logging doesn’t appear withing Xcode”.

Smokin’ Fast Blog

April 29th, 2006

I spent a large part of today “under the hood” working on this blog’s WordPress-based engine. My head hurts from all the PHP, but I am pretty happy with the results. What was I doing? Optimizations for CPU and bandwidth efficiency.

I have been pumping up DreamHost since I moved over to them a couple weeks ago. They’re still awesome, but the honeymoon did end a little bit when I got an email from them notifying me that I was exceeding my daily CPU usage allotment. Hmm? I had never even considered this before. I guess I just took for granted that servers were good and fast and they made it all work. I didn’t consider that with a virtually unlimited bandwidth quota, I would have to watch my step with how hard the server was working to fill that pipe.

I’ve been oblivious to web performance considerations, for the most part. This wake-up call from DreamHost inspired me to finally take the problems by the horns. When your site only gets a half-dozen hits per day, who cares how well it performs?. But as my traffic continues to increase, I’m starting to look at things more and more like a webmaster.

Some time ago I was chatting with John Gruber about the merits of WordPress vs. Moveable Type. He pointed out that WordPress, with its dynamic content generation, was a lot less likely to stand up to a major traffic burst than Moveable Type with its static generation. Frankly, it was the first time I’d even considered the issue – and it scared me so much it almost made me want to jump ship from WordPress. How could it be so inefficient? Basically every WordPress blog comes standard with a complete and utter inability to stand up to being slashdotted? Given the amount of traffic Daring Fireball must receive, it’s no surprise that John’s thought about this problem a lot.

But what was I going to do? Switch from WordPress? Please, no! Thankfully, the amazing WP-Cache WordPress plugin basically fixes all that. By saving a static copy of every dynamically generated request response, it achieves the best of both worlds by allowing content to be dynamically generated, but letting it stick around for a while on disk for future servings. Today I installed and activated the plugin. When the cache is on, every request that is answered gets appended with an HTML comment describing whether the request was cached or dynamically created, and how long the original dynamic creation took. I was curious to know how much time I was saving on the cached copies, so I hacked the plugin to also print a timestamp when the cached version is served. The results are pretty impressive. For example, on one entry I just looked at from my browser:

<!-- Dynamic Page Served (once) in 0.453 seconds -->
<!-- Cached page served by WP-Cache in 0.002999 seconds -->

In other words, it went from almost a half-second to almost no time at all. A huge reduction, most of which I assume would be spent as CPU time in the dynamic case. Curious about whether the cache saved you any time just now? Just look at the source for this web page or RSS feed, at the very bottom you’ll see a comment about the dynamic generation time. If it was cached, you’ll see a second comment about that. I haven’t exactly figured out everything that stimulates a cache flush for a particular URL, and it’s possible that the flushing is a little overly-cautious, but at least it’s not serving stale data.

Being so pleased with the caching success, I was in the mood to keep improving things. A reader pointed out a problem a couple months ago, which I’ve been meaning to look into. They had installed the latest beta of NetNewsWire and noticed in that application’s “Bandwidth Statistics” window, my blog was at the top of the heap for bandwidth used. The problem? A combination of my notoriously long posts, a fairly large “item count” for the feed, and a flaw in WordPress 2.0.2 that causes it to not properly return 304 (Not Modified) responses to clients who ask politely whether there have been any changes. So every time NetNewsWire refreshed, it would grab the full text of my last 10 posts!

Today I searched the web and found out that the 304 issue was in fact addressed, and the change is so simple I could type it in to the sources myself. Yee haw! I made the change and rushed over to NetNewsWire to try it out for myself. Alas, it still wasn’t working. The problem now? WP-Cache doesn’t seem to have any mechanism for supporting such a response, and since it essentially “takes over” when serving a cached copy, WordPress never gets a chance to respond. I’m not 100% sure I did this right, but I managed to hack up the WP-Cache plugin so it looks for the “If-Modified-Since:” header and, if it the specified date is not earlier than the cached copy, returns a 304 response. Seems pretty straightforward, but I’m nervous enough about it that I’ll postpone sharing the code until it’s had a chance to simmer.

These changes should have a positive effect on both my bandwidth (for whatever it’s worth) and CPU usage. But more importantly to you, they mean faster page loads in your browser, and faster subscription refreshes in your aggregator. And hopefully I’ll fall out of first place in your NetNewsWire bandwidth abusers list!

Update: My changes to WP-Cache seem pretty stable in that they’ve been running on my blog for a week or so. If anybody is interested you can download the modified file here. The only change is to the phase1 script. The mods add support for 304 responses even on cached items, and for printing the elapsed time of page load even when cached.

Let me know if you have any feedback!

Update: If you are using PHP5, you will want to make a minor tweak to WP-Cache to fix a “blank pages” bug. See this page for more information.

What’s in a Name?

April 28th, 2006

I recently wrote about Easy Programming, my pseudo-methodology for “keeping going” in the face of difficult or tedious tasks. Since then, I’ve observed an aspect of my workflow that, while seemingly among the easiest of tasks, can be the most limiting to my productivity. What is this devastating conundrum? The challenge of naming code.

I must have a christening hang-up. I get all cold-footed when the time comes to name a class, source file, method or function. Even variables! There’s a lot of pressure to come up with a name that is both instantly descriptive of the concept being represented, while also compatible with the prevailing code style, easy to pronounce, type, etc.

Could it be that the most mundane task, giving names to the commodities we trade in, could be the hardest aspect of programming?

In light of my recent thinking on Easy Programming, I was inclined to think that the best solution is to just forge ahead. Don’t let myself get caught up in such antics. If I can’t think of a class name within 5 minutes, just call it something and get on with the show. After all, after everything is working, I can always rename it if I feel strongly about it. I was getting happy with this conclusion when Jonathan Wight of Toxic Software made a statement that tipped my thinking in the other direction:

“Generally if I can’t think of a name for a class it means that when i come to refactor the code that the class wasn’t well thought-out in the first place.”

Well, shucks. That sounds downright obvious now that I’ve heard somebody else say it.

Zachery Bir pointed out that such thinking is common in OOP circles. A bad name is often identified as a code smell – something that stands out in code as a sign of potential lurking problems. An article on good naming supports exactly what Jonathan was getting at – that a badly named entity begs for refactoring.

So the dilemma becomes this: how do I keep my job easy, and name things correctly, and avoid spending an eternity doing it? My conclusion is that naming is important enough that it deserves a good length of consideration. Don’t be afraid to give yourself an hour or more! Do other stuff and let it sit in the back of your mind. You’re not wasting time. What you’re doing is designing on autopilot. When you think of the right name, it will serve as a specification for what you need to do – and specifications lead to easy programming. If you can’t deduce the right answer yourself, seek help from coworkers or the web. The articles on the C2 Wiki, including those cited above and this one on “meaningful names” go into detail about some techniques that might help you settle on the right name. There’s gotta be a right name for the class. What does it do? What should it do?

Sometimes you simply won’t be able to figure it out. A programming defeat, and it stings! At last it may be in your best interest to follow my first instinct: simply forge ahead. If you know you can get the job done and fix it later, your time may be better spent on future refactoring than on present-day moping around, trying to come up with the perfect name. Use your failure as a exploratory design experiment. It’s OK, you failed. We all do it. But whatever you do, don’t waste your time trying to come up with some “almost appropriate” name for your mistake. Don’t fake success by giving it some prestigious name that blends into the background. Name it SmadoodieCracker, or GodDamnImASuckyProgrammer, or something equally delightful. Better yet, pick a standard template and name all of your cop-out classes using this scheme: SuckyClass001, etc. Now you can do a global search for your smelly names.

Many programmers will feel hesitant to adopt such a practice. Your self-esteem is not fully developed, and you fear that coworkers will see what a fraud you are. Surely your boss will decide that you’re not senior developer material after all. And here we thought you were an infallible genius! This all may be true on a sucky team, but on a good team they’ll appreciate your candidness. And when browsing the sources to SmadoodieCracker, should inspiration strike and present a clear vision of what the class should do, they won’t think twice about overhauling your ugly mess. You owe them a beer, now.

Other people fixing your code? The easiest programming of all!