This page was originally created in late 2001. Results are for antiquated versions of the Mac OS X operating system...
UPDATE 21/11/2005: I've updated this page to include some results from Tiger. See below.
I've been making civilised attempts at switching entirely over to MacOS X since its initial release but have found the OS´s performance to be disappointing. I have therefore followed the progress of the OS with keen interest in hope of further improvements, making tests with a few tools I have found online. The tool whose results I want to discuss is Rob Terrell's Let1kWindowsBloom.
This tool measures the time it takes to open
and close 1000 windows and can be downloaded
here.
I ran several tests with this app, each time
changing some environmental variables to see how
they affected performance. Some of these variables
could be changed by altering settings in System
Preferences, but others required third-party tools,
the ones below:
ShadowKiller
- An app that removes window shadows in MacOS X
Duality 3 -
Akin to MacOS 9's Kaleidoscope, this utility lets
you change themes.
The environmental variables I changed during the
testing were the following:
Opaque Aqua - A theme identical to Aqua, but
with no transparencies.
No background image - Background in MacOS X
set to "Solid Color"
Thousands of colors - Changed to 16 bit
color
No shadows - Shadows removed with
ShadowKiller
The results below were got by running
Let1kWindowsBloom three times under each setting
and calculating the average. In all cases the Dock
was hidden and no other running applications, with
bouncing in the Dock disabled. The computer used
was a G4/450Mhz Sawtooth with 640MB of RAM and the
stock ATI Rage 128 Pro. A setting marked "X" is on,
off is "-".
|
|
|
|
Result in seconds |
|
|
|
|
55 |
|
|
|
|
54 |
|
|
|
|
54 |
|
|
|
|
53 |
|
|
|
|
45 |
|
|
|
|
54 |
|
|
|
|
48 |
|
|
|
|
49 |
|
|
|
|
41 |
|
|
|
|
38 |
It seems that neither transparency nor the
background image are important variables in this
case. The greatest speed improvement comes from
changing to 16-bit color and removing the window
shadows, especially the latter. Unfortunately the
interface becomes extremely uncomfortable with the
shadows disabled due the lack of depth in layered
windows.
New 16/08/2002
Unfortunately 10.2 seems to have
broken the functionality of Duality and
ShadowKiller so I could not include them in my
tests, but here are the results. As before, the
Dock was hidden, bouncing turned off and no other
running application, with the results a calculated
average of three runs.
|
|
Result in seconds |
|
|
54 |
|
|
52 |
|
|
50 |
|
|
49 |
There seems to be little or no
improvement in Jaguar, which is disappointing when
you consider the results of running the same test
in MacOS 9.
|
Result in seconds |
|
13 |
|
12 |
Unfortunately I did not have the original test machine available, so a scientific comparison is not possible. However, I got the following results on a 1.25Ghz Powerbook Aluminum, with 1.25GB of RAM and a 64MB ATI9600 video card.
Optimizations | Result in seconds |
None | 12 |
No background image, no window shadows | 12 |
Thousands of colors, no shadows | 12 |
No Finder running | 11 |
Perhaps unsurprisingly, quitting the Finder seems to improve results, probably because the Desktop doesn't have to be redrawn every time a window is disposed of -- only the background image.
/* * Creates and destroys 1000 windows using Carbon or Classic * * By Rob Terrell * http://www.vgg.com/rob/ * */ #include Dialogs.h #include Fonts.h #include MacWindows.h #include Menus.h #include QuickDraw.h #include TextEdit.h #include Timer.h #include stdio.h #include sioux.h static void Initialize(void) { #if !TARGET_API_MAC_CARBON InitGraf(&qd.thePort); InitFonts(); InitWindows(); InitMenus(); TEInit(); InitDialogs(nil); #endif InitCursor(); } void main(void) { int c; WindowPtr w; Rect r; UnsignedWide start, end; long elapsed; Initialize(); SetRect(&r, 100,100, 500, 300); Microseconds(&start); for (c=0; c<1000; c++) { w = NewWindow(nil, &r, "\pWindowTest", true, 0, (WindowRef)-1L, false, 0L); if (w!=nil) DisposeWindow(w); } Microseconds(&end); elapsed = end.lo - start.lo; SIOUXSettings.asktosaveonclose = false; printf("Total time to create and dispose %i windows: %d seconds (%i microseconds) ", c, elapsed / 1000000, elapsed); }
For the sake of curiosity, I decided to alter Let1kWindowBloom and make it use Cocoa calls to create 1000 windows consecutively. There seems to be little performance difference, as both almost certainly use the same lower-level calls. However, it can be interesting to see the difference in speed between buffering types. Click here to download (includes source and XCode project. And here's the code:
/* Let1kCocoaWindowsBloom * Creates and destroys 1000 windows using Cocoa calls * * By Sveinbjorn Thordarson, based on code by Rob Terrell * http://sveinbjorn.sytes.net * */ #import Foundation/Foundation.h #import Cocoa/Cocoa.h #import Carbon/Carbon.h int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; int c; NSWindow *w; // window style mask // Try changing this to a different combination of these values // to get a feeling for the overhead involved in drawing different // window types // // NSTexturedBackgroundWindowMask // NSResizableWindowMask // NSMiniaturizableWindowMask // NSBorderlessWindowMask // NSTitledWindowMask // NSClosableWindowMask unsigned int styleMask = NSTitledWindowMask; // backing store -- can be NSBackingStoreBuffered, // NSBackingStoreRetained or NSBackingStoreNonretained // The last of these is, of course, the fastest unsigned int bst = NSBackingStoreNonretained; // Window size -- performance decreases linearly with window size NSRect r = { { 100, 100 }, { 400, 200 } }; UnsignedWide start, end; long elapsed; Microseconds(&start); for (c=0; c<1000; c++) { w = [[NSWindow alloc] initWithContentRect: r styleMask: styleMask backing: bst defer: YES]; [w setTitle: @"WindowTitle"]; [w orderFront: [NSApplication sharedApplication]]; if (w != NULL) [w release]; } Microseconds(&end); elapsed = end.lo - start.lo; printf("Total time to create and dispose %i windows: %d seconds (%i microseconds) ", c, elapsed / 1000000, elapsed); [pool release]; return 0; }