Archive for 2007

How to use Plot

Saturday, June 30th, 2007

Plot is a freeware plotting and graphing application for Mac OS X. It’s good, but its documentation and UI are not very effective at explaining its most basic usage. I eventually figured out how to use it, but while it could have been much worse, it certainly wasn’t obvious. So I’m going to give you the 60-second primer that I needed.

If you’re not familiar with the basic concept of a graph: It’s zero or more data points with x and y values, lain out in a graphical depiction mapping the x and y values to positions on the graph. Plot is an application that turns your data into a graph.

This is the graph window in Plot. This is a composite screenshot showing both a bar graph and a line chart.

Plot is organized around buffers. Each buffer is a set of data: zero or more points with x and y values, and x and y error-values.

Buffers are listed and managed in the Data Inspector window, wherein Plot indicates the current buffer with a ➽ character. You edit the contents of the current buffer in the Data View window, and you edit its parameters (most of which concern the graphic display of the data) in the Inspector window (not to be confused with the Data Inspector window).

A new document doesn’t contain any buffers. You create buffers using the New Empty Buffer command in the File menu, or by importing data from various sources, including text files and MySQL databases. It even has a feature to automatically update the buffer from the database periodically, but I haven’t tried it.

You can have as many buffers as you want, and you can change the order in the Data Inspector window, using the ▲ and ▼ buttons.

The Data View is fairly straightforward, but there is one gotcha: Double-clicking the X or Y column header switches the column between number values and date values. I have no idea why this isn’t in a more obvious place instead; I actually threw away a document, thinking that it had become corrupted somehow, before I figured out later that double-clicking the column header is what tells the application to switch it.

Another pitfall: There’s no “your document is unsaved” warning. You may want to unplug your keyboard so you don’t hit ⌘W or ⌘Q by accident. ☺

The text file format is good if you want to store data independently of the Plot document (especially since Plot uses NSKeyedArchiver for its native file format). The text format is very simple: the first column is the x value, and the other column is the y value. Each record is one line. Each file is one buffer. You can import multiple buffers at a time, but you can only export one at a time.

To change the width of a bar in the bar graph, change the “symbolsize” in the Data Style pane of the Inspector. This is also used for the symbol rendering; unfortunately, there’s no way to have both a symbol and a bar graph and have them be different sizes (or colors).

To assign text along the sides of the graph indicating what the axes represent, use the Axis Text field in the Axis pane of the Inspector.

To have a legend (most useful for multiple buffers), first assign each buffer a comment in the Data Inspector, then turn on Plot Legend in the Legend pane of the Inspector. To place the legend, either use the two fields there, or use the “move legend” tool in the Inspector (which you can also activate by pressing the L key in the graph window). The move legend tool allows you to set the position of the legend by dragging within the graph window.

Here's a bar graph generated in Plot looks like.

Here’s the Plot document for the example graph used herein (compressed with bzip2).

Constantly?

Friday, June 29th, 2007

From this article about kevent and why it’s better than anything else:

Another approach is to set signal handlers to catch when I/O is available, and then put the process to sleep. […] However, the problem with this approach is that signal handling is somewhat expensive. For example a web server receiving 100 requests per minute, would need to catch signals almost constantly.

No; 100 requests per minute means one every 0.6 seconds. I do think most web servers can completely finish almost any request in less than 0.6 seconds, unless you’re dealing with a broken CGI, broken database engine, etc.—in which case, signal handling is not your performance hit.

Really, the only amount of time that matters is how long it takes for your signal handler to fork or create a thread. After that, it’s some other process/thread’s problem.

Really cheap flash memory

Thursday, June 28th, 2007

At your local Micro Center, behind the counter, they have USB flash-memory sticks for $16 for 2 GB.

Here's a photo comparing the size of the stick to the size of a US 25¢ coin. The stick is about twice as long as the quarter, and ⅔ of the width.

There is a catch: It comes with a second read-only memory device containing preinstalled software for Windows. Fortunately, this is easy to disable with a simple fstab rule.

The main storage device, on the other hand, is easily reformatted in Disk Utility. The stick is USB 2.0, as you can see from my dd results:

Plugged into my keyboard (thereby constrained to USB 1.1)

dd bs=62914560 count=1 if=/dev/zero of=temp          %/Volumes/Stick of data(0)
1+0 records in
1+0 records out
62914560 bytes transferred in 63.105605 secs (996973 bytes/sec)

Plugged directly into one of my USB 2.0 ports

dd bs=62914560 count=1 if=/dev/zero of=temp          %/Volumes/Stick of data(0)
1+0 records in
1+0 records out
62914560 bytes transferred in 11.250311 secs (5592251 bytes/sec)

In case you’re wondering, 62,914,560 bytes is 480 megabits, the theoretical maximum throughput of USB 2.0. If I were using 100% of that bandwidth, the write would have happened in one second. As it was, the write did about 5+⅓ MiB per second over USB 2.0, and 1920 MiB per second over USB 1.1.

Pretty good for $16, I think.

UPDATE 2008-11-29: Sometime in the last few months, Micro Center reorganized the front of their store. Now, the cheap store-brand flash memory is in racks right there on the counter.

And prices have come down even further, of course. Now, 4 GiB will cost you $10. And they no longer limit you to USB thumb drives: they now offer SD cards, as well.

What’s in your menubar?

Saturday, June 23rd, 2007

Synapse forwards the question: What’s in your menubar?

Here's a screenshot.
Screenshot taken 2007-06-23.

From right to left:

  1. MenuCalendarClock
  2. User MenuExtra (AKA Fast User Switching)
  3. Volume MenuExtra
  4. Text Input MenuExtra
  5. Keychain MenuExtra
  6. MemMeter (MenuMeters)
  7. NetMeter (MenuMeters)
  8. URLWell
  9. Strings Menu (lets me insert strings from a list I’ve predefined; eventually I’ll port this to a service and release it)
  10. GrowlTunes
  11. (Not shown) Adium

Of course, that’s not nearly as bad as it used to be…

(more…)

Apple Bug Friday! 63

Friday, June 22nd, 2007

This bug is hdiutil provides no facility to change bzip2 block-size. It was filed on 2007-05-25 at 13:49 PDT.

(more…)

Apple Bug Friday! 62

Friday, June 22nd, 2007

This bug is User 501 gets the admin bit after migration. It was filed on 2007-05-25 at 13:29 PDT.

(more…)

The well-hidden documentation of Core Audio

Sunday, June 17th, 2007

Ordinarily, I’d post this on del.icio.us, but this isn’t on developer.apple.com and I don’t think del.icio.us allows file: URLs.

Most use of Core Audio goes through Audio Units, but the Audio Unit API has historically been undocumented. Today, I finally found the Audio Unit documentation. Turns out that, rather than being in the /Developer/ADC\ Reference\ Library/Documentation folder (where you would expect documentation to be), it’s hidden in the /Developer/Examples folder. This documentation is so good (damn near production-quality) that I feel like I’ve struck a rich vein of gold ore.

WTF, Apple?

People I’ve met at WWDC

Thursday, June 14th, 2007

This is a partial list until Friday night, but it’s worth posting now because of all the people I met at the WWDC Bash.

Where possible, I’ve also listed their IRC nickname.

Adium-related people I met at WWDC

Other people I met at WWDC

  • Karl Adam (PantherMachina)
  • Dave Batton [Added Friday, though I met him before the Keynote]
  • Ken Ferry (kongtomorrow)
  • Andy Kim [Added Friday]
  • Paul Kim (mr_noodle) [Added Friday, though I met him after the Keynote]
  • Devin Lane (DevG5)
  • Gus Mueller (ccgus) [Added Friday]
  • Scott Stevenson [Added Friday; I’d met him previously at CocoaHeads]
  • Many Adium fans (thanks for your kind words, everyone!)

Bloggers I met at the WWDC Bash

Bloggers I met at CocoaHeads

The audience was SRO, so David and I (along with Devin and Michael Gorbach) just went off to The Studio and hacked code. After the meeting, I went up to Scott, and we shook hands and that was it. My guess is that it was a busy night and he wanted sleep.

People I’ve seen at WWDC, but did not talk to

People I saw at the WWDC Bash, but did not talk to

  • john calhoun
  • Martin Ott (I think he saw my Adium shirt and said “look, Adium!”, but it could just be wishful hearing, considering Ozomatli was blaring at the time)
  • Some other people I’m totally blanking on

A simple way to make your NSLogs and NSAsserts more informative

Wednesday, June 13th, 2007

OK, so I’m not totally radio-silent. I learned about this in a WWDC session, but since it’s already public API in Tiger (actually, it’s a GCC extension), I can talk about it.

It’s a built-in macro called __PRETTY_FUNCTION__. This is a fully-qualified human-readable signature of the function you’re in. The GCC docs don’t mention this part, but it even works in Objective-C, in addition to C++ and plain C. Here’s a test app, containing this code:

@implementation Blah(blah)
- (void)blah {
    NSLog(@"%s", __PRETTY_FUNCTION__);
}
@end

And the output:

2007-06-14 07:50:37.733 printmethod[1800] -[Blah(blah) blah]

Notice that it includes the class name, category name (if any), and method selector.

Note that that’s a C-string, not an NSCFString. Be sure to set up your format string accordingly.

Scheduling note

Tuesday, June 12th, 2007

Since I’m at WWDC, all the bugs I’m filing this week are Leopard bugs. That means that their contents are under NDA, so I can’t post them on the web. Thus, there will be no ABF this week.

ABF will return next week with at least two bugs! And yes, they will both be Tiger bugs.

Bug in the accessors generator

Tuesday, June 5th, 2007
 unsigned short multiplierBase, multiplierPower;

The output from the accessors generator:

- (unsigned) short;
- (void) setShort:(unsigned)newShort;

- (unsigned) multiplierBase;
- (void) setMultiplierBase:(unsigned)newMultiplierBase;

- (unsigned) multiplierPower;
- (void) setMultiplierPower:(unsigned)newMultiplierPower;

This is both an advisory to you and a reminder to me. I’ll be tackling this after WWDC.

Apple Bug Friday! 61

Friday, June 1st, 2007

This bug is Mac OS X should include pbzip2. It was filed on 2007-05-25 at 01:01 PDT.

(more…)

Blog spam count #2

Friday, June 1st, 2007

I’ve reset the NTT counter at 26,445 spams. Once again, next month will bring another count of spams-per-month.

I think I’ll do this every month and establish a trend. Maybe find some free graphing software and plot a graph with the counts.

iTunes is now available without DRM

Wednesday, May 30th, 2007

They’re calling it “iTunes Plus”, and the current Single-of-the-Week is available in it. Took them long enough—yesterday was the last Tuesday in May, and they didn’t even get done with it until today.

Ah, well. At least it’s finally here. Woo-hoo!

By the way, you need to update to iTunes 7.2 and agree to the iTS terms and conditions again to turn on iTunes Plus. The actual T&C haven’t changed, but the Terms of Sale have.

What if we had a language keyword for ownership?

Tuesday, May 29th, 2007

For example:

retained NSImage *myImage;

mutablyCopied NSTextStorage *myTextStorage;
NSLayoutManager *layoutManager; //Owned by myTextStorage
NSTextContainer *textContainer; //Owned by layoutManager

Or instead of retained, we could have a keyword for non-ownership, with retain being the default for instance variables:

NSImage *myImage; //Retained by default

mutablyCopied NSTextStorage *myTextStorage;
borrowed NSLayoutManager *layoutManager; //Owned by myTextStorage
borrowed NSTextContainer *textContainer; //Owned by layoutManager

(Hopefully, this is already common, but using comments rather than language keywords.)

Perhaps these could be implemented using something like Python’s decorator syntax:

#define retained @ownership(retain)
#define copied @ownership(copy)
#define mutablyCopied @ownership(mutableCopy)

//What the code looks like after macro-expansion, or without using macros at all:
@ownership(copy) NSString *myTitle;

Either way, the correct retain/copy/mutableCopy/release magic would happen automatically on any assignment. The only manual work still involved would be:

- (void)dealloc {
	[myTimer invalidate];
	myTimer = nil; //Implicitly releases myTimer

	myTextStorage = nil; //Implicitly releases myTS (and on death, it releases its LM, and that releases its TC)

	[super dealloc];
}

This would make it totally impossible to forget to retain something (forgetting to retain or copy things leads to double-releases or zombie objects), and make it much harder to retain when you should copy or vice-versa. It would also make your header much richer in documentation, and the more you can learn from the header, the easier reading the implementation will be.

Now that’s what I call a speed-up

Tuesday, May 29th, 2007

CPU Usage 0.4 creates and throws away an NSImage every time a view (one per processor) updates. This is incredibly wasteful: The application uses about 0.7% of a CPU on my system.

But I decided that I can make that faster. Profiling (thanks, Shark!) revealed that the hot spot was creating, measuring, drawing, and throwing away the attributed string that goes into the NSImage. That’s not hard to optimize away: as the old doctor joke goes, “stop doing that”.

So I created a couple of branches, and went in two different directions:

  • Direction A uses NSLayoutManager—specifically, one NSTextStorage, one NSLayoutManager, and one NSTextContainer for every (CPU, percentage) pair. A view can display any of 101 percentages (0–100%), so on my four-core system, this branch creates 404 storages, 404 managers, and 404 containers.
  • Direction B uses an NSImage, just like 0.4 does, but keeps it around.

Both branches are written to create the (NSImage|NSTS, NSLM, and NSTC) lazily, but for testing, I added this code to force the creation of all the cached objects up front so that my time-trials would represent normal usage (that is, usage after all the objects have been created and cached):

- (void)drawRect:(NSRect)rect {
    //BEGIN TEMP
    if(!(percentageImages[0U])) {
        static BOOL isInDrawRect;
        if(!isInDrawRect) {
            isInDrawRect = YES;

            NSLog(@"Preloading percentage images for CPU %u", CPUNumber);
            NSRect tempImageBounds = [self bounds];
            NSImage *tempImage = [[NSImage alloc] initWithSize:tempImageBounds.size];
            [tempImage lockFocus];
            for(float usage = 0.0f, maxUsage = 1.01f; usage < maxUsage; usage += 0.01f) {
                [self setCPUUsage:usage];
                [self drawRect:tempImageBounds];
            }
            [tempImage unlockFocus];
            [tempImage release];
            NSLog(@"Done preloading percentage images for CPU %u", CPUNumber);

            isInDrawRect = NO;
        }
    }
    //END TEMP

    ⋮
    (The rest of -drawRect: is here)
}

That’s from the NSImage branch, but the code in the NSLayoutManager branch is basically the same. (Note: tempImage is not the cached image; it’s just a throwaway destination for the drawing done by -drawRect: in the inner call.)

Once I had finished this, and fully optimized both branches using Shark, the next step was to try them out and see how they fare.

I launched all three versions of CPU Usage, and then did the following:

# Watch the CPU usage of the CPU Usage processes for five minutes (300 seconds)
top -l 300 | fgrep 'CPU Usage' > top-CPU_Usage.txt      %/Volumes/RAM Disk(130)
___
# Fourth column (as determined by whitespace) is CPU usage
fgrep 221 < top-CPU_Usage.txt  | awk '{ print $4; }' > top-CPU_Usage-0.4.txt
___
fgrep 1121 < top-CPU_Usage.txt | awk '{ print $4; }' > top-CPU_Usage-NSLM.txt
___
fgrep 1118 < top-CPU_Usage.txt | awk '{ print $4; }' > top-CPU_Usage-NSImage.txt
___
# The results, in percent of one CPU
~/Python/avg.py < top-CPU_Usage-0.4.txt                   %/Volumes/RAM Disk(0)
0.671
___
~/Python/avg.py < top-CPU_Usage-NSLM.txt                  %/Volumes/RAM Disk(0)
0.667
___
~/Python/avg.py < top-CPU_Usage-NSImage.txt               %/Volumes/RAM Disk(0)
0.737

Note: For timing purposes (since top’s CPU-usage display is in tenths of a second), I divided CPU Usage’s sample interval by ten. Normally, it samples every 0.5 sec; the two prototypes above sample every 0.05 second (that is, ¹⁄₂₀ sec instead of ¹⁄₂ sec).

This means that to compare them to 0.4, you must divide the results by ten to adjust them back to the half-second interval that a release would have. Here are the *real* results:

0.4 0.671%
NSImage 0.0737%
NSLayoutManager 0.0667%

So CPU Usage 0.5, with the cached-NSLayoutManager behavior, will use ¹⁄₁₀ as much CPU as 0.4 does. And here’s what that looks like:

All four processors show 0% usage.

Sweet!

I’d forgotten how awesome Sherlock is

Sunday, May 27th, 2007

Compare this translation interface (what I’ve been using):

Babel Fish, with its small input textarea,
Babel Fish (in Camino, because none of my other browsers work with it)

to this one (what I should be using):

Sherlock, with its text fields that take up almost the entire window.

I used to hate Sherlock under Mac OS 9—I went so far as to custom-install Find File from Mac OS 8.5. But Sherlock under Mac OS X is pure awesome.

Now, if they kill it in a future OS version, I’ll be sad. And I may end up cherry-picking from the old OS disc again.

Inspirational posters

Saturday, May 26th, 2007

For your enjoyment:

Parallelism: beautiful It's thing. a

And an alternate version:

Threading: beautiful It's thing. a

Created with Motivator. Choice of screenshot inspired by Gus Mueller’s “viii”.

ADDED 2007-05-26: Here’s a third version using a photo from thefunniest.info.

Apple Bug Friday! 60

Friday, May 25th, 2007

This bug is NSImageInterlaced has no effect. It was filed on 2007-05-12 at 00:50 PDT.

(more…)

Apple Bug Friday! 59

Friday, May 25th, 2007

This bug is The NSImageInterlaced, it does nothing!. It was filed on 2007-05-12 at 00:29 PDT.

(more…)