Feb 25

Sometimes it’s important to know what version of Mac OS X your users are running, especially when making decisions on what versions of OS X to support in future software releases. In the case of Seasonality 2.0, I have decided to take advantage of all the developer changes in Leopard, both to make Seasonality a better application, and to shorten my development time (thus giving me more time to work on additional features).

Previously, I haven’t performed any OS statistics on user data. It would be easy to do, since Seasonality downloads forecast and image data from a web server here at Gaucho Software, but I haven’t written the code required. However, some of these Seasonality data requests are using the typical CFNetwork methods of downloading data, and these connections provide the current CFNetwork version in the HTTP UserAgent, and thus will show up in my web server logs.

The problem is that I have been unable to find any kind mapping between CFNetwork versions and the corresponding version of Mac OS X. I decided to take it upon myself to generate (and hopefully maintain) such a list here. Most of this data is from viewing the Darwin source code on Apple’s web site, but some of these are just from personal observations, and some are educated guesses (marked with a question mark).

HTTP UserAgent   Version of Mac OS X
CFNetwork/221.5   Mac OS X 10.5.2
CFNetwork/221.2   Mac OS X 10.5.2 Developer Seed?
CFNetwork/220   Mac OS X 10.5.1?
CFNetwork/217   Mac OS X 10.5?
 
CFNetwork/129.22   Mac OS X 10.4.11
CFNetwork/129.20   Mac OS X 10.4.9 - 10.4.10
CFNetwork/129.18   Mac OS X 10.4.8
CFNetwork/129.16   Mac OS X 10.4.7
CFNetwork/129.13   Mac OS X 10.4.6
CFNetwork/129.10   Mac OS X 10.4.4 - 10.4.5 (Intel)
CFNetwork/129.9   Mac OS X 10.4.4 - 10.4.5 (PPC)
CFNetwork/129.5   Mac OS X 10.4.3
CFNetwork/128.2   Mac OS X 10.4.2
CFNetwork/128   Mac OS X 10.4.0 - 10.4.1
 
CFNetwork/4.0   Mac OS X 10.3 or earlier
Nov 06

I’m thrilled to link to a major update of DynDNS’s Mac client, DynDNS Updater 2.0. I’ve been working on the DynDNS Updater for quite some time, and this release is a complete re-write that has a lot of new functionality. Looking at 1.x and 2.0, you would never know the projects were related; there are far too many changes to even list. To try and summarize, DynDNS Updater 2.0 is built from the ground up to give a completely modern Mac experience to people who use the services provided by DynDNS. The updater now has auto Sparkle updating built-in, Growl integration, a custom Dashboard Widget, and an interface that looks right at home on both Tiger and Leopard. Core technologies like OpenSSL, libcurl, and pthreads are used on the back-end.

In case you aren’t familiar with DynDNS as a company, their products solve the problem of managing DNS for just about every type of user, from individuals to large companies. I believe Dynamic DNS is the project that is most well-known (at least that is how I heard of them years ago), giving users with dynamic IPs a method of having a static name point to their computer. The DynDNS Updater’s primary function is to watch out for IP address changes on your Mac, and let the DynDNS servers know when there is a change. The updater is broken up into two separate executables, one is a Cocoa application where you configure your accounts and hosts. The other executable is a background daemon running 24/7 that performs all the grunt work.

I started working on version 2.0 last year. Jeremy Hitchcock and the rest of the DynDNS crew had some nice feature ideas for the next version, and I mocked up a design that would implement some of these features. I was pretty excited about the project and started working on what was to be a fairly advanced update. Fast forward to around March or April of this year when the first beta was being wrapped up. This beta had the foundation of a solid background daemon where I tried to stick to the basic POSIX libraries, so it could run on multiple platforms. At one point, I was regularly compiling it on Linux and it was working well (I haven’t tried this for quite some time since then). The daemon was completely threaded, and supported multiple network connections. Unfortunately, while the code design was solid and the product had a lot of nice new features, the UI was horribly difficult to use and the interface to configure these complex setups was not pretty. The mock-ups looked nice, but actually using it is where we ran into problems. Seemingly simple operations took multiple steps, because a lot of advanced options had to be taken into account.

Enter FJ de Kermadec and his team at Webstellung. They suggested bringing the project back to basics–thinking more about the typical use case and not all the features we could give to power users in unique situations. Webstellung put together some very impressive UI design mock-ups to get things started. Jeremy gave the go-ahead, and it was back to the drawing board as I began coding up the fresh interface. Fortunately, since the daemon code was designed with flexibility in mind, it could be re-used by dropping the new interface on top of it. The initial UI creation went pretty quickly, and within a few months a new application was born. The first beta was ready just before WWDC this year. As soon as I started using this UI, I knew it was a keeper. There were a few adjustments that had to be made, but overall the interface is very intuitive. After the functionality was mostly complete, it was time to focus on the interface polish. We went through several iterations of the software, catching small changes here and there that all added up to a nice shiny app.

If you’re currently using DynDNS Updater 1.2, definitely upgrade to version 2.0. And if you aren’t, download the app anyway and check it out. Dynamic DNS accounts are free for up to 5 hosts, and it’s pretty easy to set everything up.

Sep 10

I’m not sure if it’s just me, but for some reason OpenGL coding involves a lot of trial and error before getting a feature such as lighting, blending, or texture mapping to work correctly. The past few days I have been working on adding texture compression to my OpenGL map test project. Ultimately, this code will be merged with the rest of the Seasonality source tree, and it’s going to look pretty cool.

Most OpenGL developers will use regular images and possibly compress them when loading them as a texture on the GPU. This is fairly straightforward, and just involves changing one line of code when loading the texture. Note that this is a huge gain when it comes to graphics memory savings, as I was using about 128MB of VRAM when texture compression was disabled and only around 30MB with compression enabled. I wanted to accomplish something a bit more difficult though. I’m going to be using several thousand textures, so I would like to have OpenGL compress them the first time Seasonality is launched, and then save the compressed images back to disk so concurrent launches will not require the re-compression of the imagery.

The problem I ran into was not enough developers are using this technique to speed up their application, so sample code was scarce. I found some in a book I bought awhile back called “More OpenGL Game Programming,” but the code was written for Windows, and it didn’t work on Mac OS X. So I dove deep into the OpenGL API reference and hacked my way through it. The resulting code is a simplification of the method I’m using. It should integrate with your OpenGL application, but I can’t guaranty this completely because it is excerpted from my project. If you’re having a problem integrating it though, post a comment or send me an email.

First, we have some code that will check for a compressed texture file on disk. If the compressed file doesn’t exist, then we are being launched for the first time and should create a compressed texture file.

- (bool) setupGLImageName:(NSString *)imageName
         toTextureNumber:(unsigned int)textureNumber
{
   GLint width, height, size;
   GLenum compressedFormat;
   GLubyte *pData = NULL;	

   // Attempt to load the compressed texture data.
   if (pData = LoadCompressedImage("/path/to/compressed/image", &width, &height,
       &compressedFormat, &size))
   {
      // Compressed texture was found, image bytes are in pData.
      // Bind to this texture number.
      glBindTexture(GL_TEXTURE_2D, textureNumber);

      // Define how to scale the texture.
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

      // Create the texture from the compressed bytes.
      glCompressedTexImage2D(GL_TEXTURE_2D, 0, compressedFormat,
                             width, height, 0, size, pData);

      // Define your texture edge handling, here I'm clamping.
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP);
      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
      // Free the buffer (allocated in LoadCompressedImage)
      free(pData);
      return YES;
   }
   else {
      // A compressed texture doesn't exist yet, run the standard texture code.
      NSImage *baseImage = [NSImage imageNamed:imageName];
      return [self setupGLImage:baseImage toTextureNumber:textureNumber];
   }
}

Next is the code to load a standard texture. Here we get the bitmap image rep and compress the texture to the GPU. Next we’ll grab the compressed texture and write it to disk.

- (bool) setupGLImage:(NSImage *)image
         toTextureNumber:(unsigned int)textureNumber
{
   NSData *imageData = [image TIFFRepresentation];
   NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithData:imageData];
   // Add your own error checking here.

   NSSize size = [rep size];
   // Again, more error checking.  Here we aren't using
   // MIPMAPs, so make sure your dimensions are a power of 2.

   int bpp = [rep bitsPerPixel];

   // Bind to the texture number.
   glBindTexture(GL_TEXTURE_2D, textureNumber);
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

   // Define how to scale the texture.
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

   // Figure out what our image format is (alpha?)
   GLenum format, internalFormat;
   if (bpp == 24) {
      format = GL_RGB;
      internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
   }
   else if (bpp == 32) {
      format = GL_RGBA;
      internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
   }

   // Read in and compress the texture.
   glTexImage2D(GL_TEXTURE_2D, 0, internalFormat,
                size.width, size.height, 0,
                format, GL_UNSIGNED_BYTE, [rep bitmapData]);

   // If our compressed size is reasonable, write the compressed image to disk.
   GLint compressedSize;
   glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,
                            GL_TEXTURE_COMPRESSED_IMAGE_SIZE,
                            &compressedSize);
   if ((compressedSize > 0) && (compressedSize < 100000000)) {
      // Allocate a buffer to read back the compressed texture.
      GLubyte *compressedBytes = malloc(sizeof(GLubyte) * compressedSize);

      // Read back the compressed texture.
      glGetCompressedTexImage(GL_TEXTURE_2D, 0, compressedBytes);

      // Save the texture to a file.
      SaveCompressedImage("/path/to/compressed/image", size.width, size.height,
                          internalFormat, compressedSize, compressedBytes);

      // Free our buffer.
      free(compressedBytes);
   }

   // Define your texture edge handling, again here I'm clamping.
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

   // Release the bitmap image rep.
   [rep release];

   return YES;
}

Finally we have a few functions to write the file to disk and read it from the disk. These functions were pulled almost verbatim from the OpenGL book. In the first code block above we called LoadCompressedImage to read the texture data from the disk. In the second code block, we called SaveCompressedImage to save the texture to disk. Nothing really special is going on here. We write some parameters to the head of the file, so when we go to read it back in we have the details. Bytes 0-3 of the file are the image width, 4-7 is the image height, 8-11 is the format (GL_COMPRESSED_RGB_S3TC_DXT1_EXT or GL_COMPRESSED_RGBA_S3TC_DXT5_EXT), 12-15 is the size of the image data in bytes, and bytes 16+ are the image data.

void SaveCompressedImage(const char *path, GLint width, GLint height,
                         GLenum compressedFormat, GLint size, GLubyte *pData)
{
   FILE *pFile = fopen(path, "wb");
   if (!pFile)
      return;

   GLuint info[4];

   info[0] = width;
   info[1] = height;
   info[2] = compressedFormat;
   info[3] = size;

   fwrite(info, 4, 4, pFile);
   fwrite(pData, size, 1, pFile);
   fclose(pFile);
}

GLubyte * LoadCompressedImage(const char *path, GLint *width, GLint *height,
                              GLenum *compressedFormat, GLint *size)
{
   FILE *pFile = fopen(path, "rb");
   if (!pFile)
      return 0;
   GLuint info[4];

   fread(info, 4, 4, pFile);
   *width = info[0];
   *height = info[1];
   *compressedFormat = info[2];
   *size = info[3];

   GLubyte *pData = malloc(*size);
   fread(pData, *size, 1, pFile);
   fclose(pFile);
   return pData;
   // Free pData when done...
}

Hopefully this will save someone development time in the future. If you catch any errors, let me know.

Aug 09

It’s been almost two months since I’ve posted here, so to avoid the risk of this blog becoming a dinosaur, I thought I would post an update.

Katrina and I returned from our 6-7 week road trip in the beginning of July. We drove out to California at the end of May, and stayed with family for several weeks (also hitting WWDC, of course). On the way out there, we took the northern route, hitting Mt. Rushmore, Yellowstone, the Tetons, and the Salt Flats. On the way back, we started in Santa Monica and drove Route 66 all the way through St. Louis, taking the freeway the rest of the way home after running out of time. We’ll have to drive the rest of Route 66 from St. Louis to Chicago sometime soon. Overall, it was quite a trip. Watch my Flickr stream for photos of the trip.

Been working on finishing up DynDNS Updater 2.0, which will hopefully be ready soon. The app is looking pretty good. A lot of smaller details have been improved upon since beta 5, that collectively improve the application quite a bit.

Trying to spend some time working on Seasonality’s international forecast as well. I’ll post more on this at a later point in time, but I’ve created some cool imagery and animations that I’ll be using to tweak the forecast generator to make it more accurate.

C4 is coming up this weekend! I’ll be taking off for Chicago tomorrow for a weekend of Indie fun. I’ll be showing an entry for the Iron Coder Live contest…which reminds me I still need to fix a bug or two there. Should be a blast. I’ll most likely be keeping my Twitter feed up to date more than posting here about stuff.

Speaking of Twitter, I started Twittering (is that a word?) a few months ago, and I’m hooked. If you don’t know, Twitter is a place to post Tweets, which are short bits of text (no longer than 160 characters), usually telling others what you’re up to. My first thought was how much time I would be wasting by doing this, but the whole idea is that posting a Tweet is supposed to be really quick. It provides some nice breaks throughout the day, and the community building around the site is pretty amazing. Check out my Twitter page, and if you’re interested, sign up and start using Twitter yourself.

That’s all folks…

Jun 15

End-users often ask me what exactly happens at WWDC, or any other development conference for that matter. The question can catch me off-guard. I’ll stumble around for a minute or two as I struggle trying to explain exactly what I get out of a conference like C4 or WWDC. Rob Griffiths from Macworld is attending WWDC this week, and wrote an article on MacCentral to explain just that…

The more immediate connection to Apple employees is certainly one of the biggest advantages of attending WWDC, and I have taken advantage of this a few times this week. However, if I had to choose one key reason to attend a developer conference like this, it would be to have the opportunity to connect and share ideas with other indie developers. Arguably the most innovative applications come from development shops with fewer than 5 developers. These are the applications on the leading edge. Being an indie developer gives us flexibility to choose the latest technologies, and WWDC is a great place to share ideas and talk about how we handle business, marketing, and customer support.

Last night, while listening to Ozomatli perform live at the WWDC San Francisco Bash, I had the pleasure of talking with Luis de la Rosa, Brian Cooke, Tom Harrington, and Lemont Washington about such topics. Other than Luis, I hadn’t spoken to any of these developers much, but it was great extending some connections and talking about Leopard technologies and their effects on our own applications.

Of course a big attraction of WWDC is learning the new APIs and improving our development skills, but that’s just part of the picture. Between the instructional sessions, access to Apple engineers, and sharing ideas with other developers, WWDC is an awesome developer conference. It’s definitely an event I wouldn’t want to miss.

Jun 12

I’m typing this from a fresh developer build of Leopard on my MacBook Pro. I’d have to say that this build is much more stable than the last couple of releases.

If you’re a die-hard Mac user (or even if you aren’t), you have probably heard of the various announcements Apple made yesterday. I thought I would run through the most notable announcements and add some commentary. There were three main foci of the keynote: Leopard, Safari for Windows, and the iPhone.

Leopard

Leopard consumed the majority of the keynote. Steve Jobs went into detail on just 10 of the 300 new features in Leopard. To me, the UI changes were the most significant. Steve went over topics like Time Machine, Spaces, Boot Camp, and 64-bit support, but all of these were talked about at WWDC 2006. The UI changes are fairly substantial, and I imagine there will be quite a bit of commentary regarding these changes across the blogosphere.

The first thing users will notice is the change in the Desktop, which includes the system icons, menubar, and the Dock. The Dock redesign is simply stunning. It’s a very polished, 3-dimensional implementation. The reflections are perfect, and about the only adjustment I would make is with the application shadows, which are actually above the icons. I understand why it was designed this way (as a visual separator of the icon from background content), but it doesn’t make visual sense. Otherwise, I dig it.

Likewise, stacks is a great new feature that should have been implemented by Apple 10 years ago when they originally patented the idea. This is going to make my downloads directory much more manageable. It’s also very useful for traversing directories. When you have a stack of directories, if one of those directories is clicked on, the stack updates itself with the contents of the child directory. This will be a great way to access development project files I’m working on.

However, it’s not all perfect… The folder icons and menubar both need some improvement. To begin with, the icons do not have enough detail. They look like blue blobs from a distance. This is especially noticeable when it comes to “special” directories like Music and Movies. The categorical aspect of the icon is all but distinguishing. I believe all the folder icons need to be made more distinct.

The menubar changes are probably the worst part of the Leopard redesign. The opacity of the entire menubar is around 50%, which really makes the menu titles difficult to read depending on the desktop picture you choose. When a menu is selected, it’s transparency is normal, which is good, but it looks ridiculous under the translucent menubar. At the very least, the menubar needs to fade in to 100% opaque on mouseover. I expect there will be dozens of 3rd party utility hacks to get around this issue, if the menubar makes it as-is into the final release of Leopard.

Update (6/16): That didn’t take long… Here’s the first hack now.

The nicest change about the Leopard desktop is the look of application windows. Finally, Apple is back to a single window layout–merging the standard, brushed metal, and unified layouts into a single, standard window. While it is a bit dark, overall the design is pretty slick. The important point here is that now developers don’t have to choose what kind of base interface to use in their applications. Leopard windows have a single look, and now UI designers can match their icons, views, and controls to that window layout.

Quick look is a nice new feature in Leopard. I really think this feature has the potential to push Preview.app into obsolescence. It’s very easy to use to display images, presentations, spreadsheets, PDF and word documents. With a quick change to full screen mode, I think this is going to really improve the way users browse through their documents.

The new Finder will probably be seen as a minor upgrade, but I believe it to be significant. The current Finder contains a lot of legacy Carbon code, and Leopard’s Finder should improve performance. It will be difficult to say until I spend more time using it, but I’m hoping threading support is more robust… I hate seeing the spinning beach ball when I get disconnected from a network server, and the new Finder reported fixes this issue. The design also feels cleaner–more enjoyable to use. It’s a subtle, but noticeable improvement. Coverflow also looks neat, but I can only imagine using it in directories filled with images, and even then I would only really use it to scan all the images in general.

The biggest improvements in Leopard will be completely transparent to users… Apple’s going a long way by offering new development technologies behind the scenes, and users will see evidence of these changes in future 3rd party application releases.

Safari for Windows

Safari for Windows is a huge bonus in my eyes. Just from using IE 7 for a few hours, the user interface is a nightmare. Having Safari as an option on my Boot Camp partition here will be very nice. I think Apple is approaching it the right way by marketing towards the web developers with Safari 3’s web debugging features. If web developers are using Safari to develop their applications, then we’re going to see a lot more site compatibility cross-platform. Apple’s plan to market Safari on Windows through their iTunes downloads was vague at best, but if they really do have a million iTunes for Windows downloads every day, that should give them a lot of momentum on entering the Windows browser market.

iPhone “SDK”

Apple’s iPhone announcement was a joke, and far from the “sweet” deal Steve used to describe the paradigm. Developing a web page is not the same as developing an application for the iPhone. Sure, it’s nice that web pages can initiate calls, emails, or physical address searches, but that is not a substitute for developing full iPhone applications. First, while living in a large metropolitan area may keep your iPhone connected 100% of the time, I think that will be far from reality. Without an internet connection, a web page application is useless. Furthermore, applications deserve a position on the user’s home screen. Opening Safari and navigating through bookmarks just to find an application is unacceptable.

In the end, I think John Gruber summarized it best: “It’s great that iPhone seems to have a killer Safari web browser. No doubt there are going to be some terrific web apps targeting iPhone. But there are a ton of great ideas for iPhone software that can’t be done as web apps.”

The Unannouncement

Several media outlets are referring to this years keynote as an unannouncement. While I agree that the keynote failed to show any fancy new hardware or groundbreaking new software, the presentation was packed with details of Apple’s path forward. This is a developer’s conference. The new details shown in Leopard, especially when it comes to user interface design, is important when designing our own applications. In that respect, the keynote showed some nice new UI changes that I think will help bring application consistency back into the picture. Mac OS X is a constantly evolving platform, which I think stems from the semi-frequent release cycle Apple sticks to. Getting a better preview of Leopard’s features gives developers a 4 month headstart on evolving their own applications with the OS, and that’s why this conference is worth it’s cost of admission.

Feb 13

I was working on some code to uninstall an application, and was pleasantly surprised to find that Cocoa’s NSUserDefaults class will remove the application’s preferences file from ~/Library/Preferences if you remove all the keys:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *keys = [[defaults dictionaryRepresentation] allKeys];

int i, count = [keys count];
for (i = 0; i < count; i++) {
   [defaults removeObjectForKey:[keys objectAtIndex:i]];
}

[defaults synchronize];

It’s not often you find uninstall options for OS X applications, but it’s nice Apple’s engineers thought about this case and handle it appropriately.

Aug 08

Between all the great sessions here at WWDC yesterday and Buzz’s excellent blogger party last night, I’ve had just about 0 time to blog about anything that has been announced here. The typical news sites have been posting all the details on Mac OS X Leopard that Steve talked about yesterday, but I thought I would add a couple of my own comments on Leopard.

First, though I’m under NDA for a lot of the content here, I’ll just say that Leopard adds a lot of nice features for developers. I would not be surprised to see a lot of applications next year requiring Leopard. I’m sure some Tiger/Panther users will feel a bit left out, but the development time can be collapsed greatly, and these apps will be a lot more polished.

64 bit is a big buzzword around here. It is a big deal…even with 64 bit POSIX available at the UNIX layer in Tiger. That was nice, but it meant that only command-line applications that used straight POSIX libraries would have the ability to run 64 bit. As was mentioned in the keynote, Apple has extended 64 bit support all the way up to the Cocoa and Carbon layers…completing the transition to 64 bit for Mac users. I think this will allow some very high-end scientific applications to provide absolutely beautiful visualization displays without having to write a bunch of extra code to handle 64 bit data processing in a different process on the back-end. I haven’t tried building Seasonality for 64 bit yet, but I suspect that it will provide a slight speed improvement on 64 bit machines because the satellite image is highly accelerated in hardware using the Accelerate framework. 64 bit processors may be able to generate a new satellite image up to twice as fast. I’ll update my blog with performance results on this sometime in the future.

Mail.app changes seem to be aplenty. I haven’t loaded the Leopard preview on my MacBook Pro yet to see just how much has been improved, but already I’m impressed. The templates look to be a good idea, but I can’t see myself using them too often. I’m sure there will be a subset of Mac users that will get a kick out of that though. The notes feature strikes me as a big chunk of bloatware tacked on to Mail. If you need to take notes, there should be another place to do it outside of your inbox. Sure, people spend a lot of time in Mail, and I’m sure a lot of people take notes while reading/responding to email, but that doesn’t mean that notes should be an integrated feature. It seems that a much better solution to write a new system-wide notes application that would let you bring up an interface with a hotkey, type something in, and dismiss it.

Apple still hasn’t updated the Finder. I really hope this is one of the “top secret” features they aren’t releasing until the end. The Finder is something Mac users spend a lot of time using, and the amount of legacy code still in there is pretty staggering. At the very least, the Finder needs to use more threading, but really they should start from scratch and try to implement something that is more efficient. They should also revisit usability. When using the Finder with a modern system with several hundred thousand files, it takes awhile to navigate to where you want to be (Note: this applies to all the current file-system-exploring applications I’ve used on any platform). Spotlight improves this situation somewhat, but it is still a pretty big problem and will only get worse as hard drive capacities skyrocket as they have been in recent years.

Despite these drawbacks, Leopard as a whole is a big improvement. Time Machine and Spaces are greatly welcomed, Core Animation will be a huge win for the usability of Leopard applications and the iChat improvements seem pretty solid.

Feb 01

A few Mac indie developers like Gus and Luis are running some unofficial developer benchmarks to judge the performance between PowerPC and Intel Macs. The benchmark is compiling Subversion, and it’s a pretty good method of metering performance impact because we spend all day compiling. :-)

Anyway, I thought I would share the results from my dual 2.5Ghz G5 with 2.5GB of RAM, and to make the mix a little more interesting, I’ve also benchmarked a server here with a single Athlon64 3200+ processor (2Ghz) and 1GB of RAM running Kubuntu Linux.

Dual 2.5Ghz G5:
   make -j2
   3:22.64 with 174% CPU usage

   make -j4
   3:20.73 with 179% CPU usage

   make -j8
   2:34.94 with 179% CPU usage

   make -j12
   2:37.82 with 178% CPU usage

Athlon64 3200+:
   make -j2
   3:15.81

   make -j4
   2:59.59

   make -j8
   2:58.68

I was surprised to see that even though the Athlon box has only a single CPU, the performance is right up there with the dual G5. Also, from Luis’ benchmarks, it looks like my MacBook Pro numbers will be pretty competitive with the G5, though it will be interesting to see how a slower disk effects the benchmarks. Speaking of disk, I should mention that the Athlon box was compiling on a 3 disk RAID 5 partition. Disk usage while compiling should be negligible, but it might skew the numbers a bit.

Now if only Apple would support distributed compiling to any other machine with gcc installed, then I could split my work between the G5, Athlon, and forthcoming MacBook Pro. :-)

Sep 27

There’s a quite interesting blog post over on Ridiculous Fish about how floats are formatted in memory and what kinds of numbers they can represent. This should be required reading for every Computer Science student. I wasn’t taught any of this at UCSB except for the mantissa/exponent way of representing a float and that sometimes an integer stored in a float was not really an integer.