Vincent Gable’s Blog

March 7, 2008

Low Level Optimization Decays With Time

Filed under: MacOSX,Programming,Tips
― Vincent Gable on March 7, 2008

Did you know that hand-optimized assembler is slower then allegedly “slow” languages, say, Lisp or JavaScript? It’s true, if you wait long enough.

Imagine you have found some old hand-tuned Lisp code, and a hand-tuned PDP-1 assembly language version. If you executed both programs today, using a modern Lisp interpreter and a modern PDP-1 emulator, the Lisp code would perform much better. That’s because it could take advantage of all the improvements in Lisp interpreters and computers since the 1960’s, while the PDP-1 code would be held back by trade-offs made long ago to appease obsolete hardware.

I expect that ultimately JavaScript will outperform contemporary SSE code, because hardware inevitably becomes obsolete over time.

When assembly code becomes obsolete, you are stuck with two slow options. Use obsolete hardware to execute the code, or emulate your obsolete hardware on a new computer (since computers keep getting faster, emulation will become the fastest choice). Meanwhile the high-level code will still be executable, and able to take advantage of all subsequent hardware improvements.

Some x86 instructions are already obsolete; by which I mean they give worse performance then more common instructions.

Assembly/Compiler Coding Rule 31. (ML impact, M generality) Avoid using complex instructions (for example, enter, leave, or loop) that have more than four µops and require multiple cycles to decode. Use sequences of simple instructions instead.

Intel®64 and IA-32 Architectures Optimization Reference Manual

You could say that this is all academic, because in half a century the code you wrote today will be irrelevant, and I would agree. PDP-1 vs Lisp was hypothetical hyperbole, show that the benefits of low-level optimization decrease the longer the code is in use, because the advantages compared to high-level code decrease over time.

What really drove this home for me was Apple’s switch from PPC to x86. Suddenly all the AltiVec code I’d ever written was obsolete. If someone bought a new Mac, my AltiVec code would be emulated, and slower then unchanged (but recompiled) C code! I could have reused existing AltiVec code to create SSE code, but then I would be stuck doing optimization work every time a sufficiently new computer came out.

Algorithmic-level optimization holds it’s value over time; low-level optimization does not. However, software is such a rapidly-changing environment that a short-term investment can still make a hell of a lot of sense.

March 5, 2008

Calling the Command Line from Cocoa

Filed under: Cocoa,MacOSX,Objective-C,Programming,Tips,UNIX | , , , ,
― Vincent Gable on March 5, 2008

The best way to call a shell-command from Coca is by using an NSTask. Here are the three resources on using an NSTask that I found the most helpful:
CocoDev’s write up
A few quick exaples
NSTask Class Refrence

And here is some sample code to do it for you. You are free to use this code however you please, but attribution is always appreciated. The two principle functions are:

+ (NSString*) executeShellCommandSynchronously:(NSString*)command executes the command “command” with sh, wait until it finishes, and return whatever it printed to stdout and stderr as an NSString.
CAUTION: may deadlock under some circumstances if the output gets so big it fills the pipe. See http://dev.notoptimal.net/search/label/NSTask for an overview of the problem, and a solution. I have not experienced the problem myself, so I can’t comment.

executeShellCommandAsynchronously: will have sh execute command in the background, without blocking anything.

For quick hacks, the POSIX int system(const char* command) function, might be a good one-line solution. It synchronously evaluates command with sh.

Enjoy!

EDITED 2009-11-29: this code probably won’t have the same $PATH you would get if you used Terminal. See this question on stackoverflow for more details. A solution that seems to work is to do,

    [task setLaunchPath:@"/bin/bash"];
    NSArray	*args = [NSArray arrayWithObjects:@"-l",
    				 @"-c",
    				 commandlineHere,
    				 nil];
    [task setArguments: args];

This launches bash (not in sh compatibility mode), and -l (lowercase L) tells it to “act as if it had been invoked as a login shell”. I haven’t tested this on systems where bash isn’t the default shell. There are lots of ways $PATH could be set, and I haven’t tested them all. But you are almost certainly going to be OK if everything you refer to is in /usr/bin:/bin:/usr/sbin:/sbin.

February 28, 2008

Useful MacOSX Terminal Commands

Filed under: MacOSX,Tips,UNIX | , ,
― Vincent Gable on February 28, 2008

Here are some OS X specific terminal commands that I have found useful, and you might not be aware of. Running man command in the Terminal will give you more information about command as it is on your system.

open
open file will open file the same way it would have been opened if you double-clicked it in the Finder. You can also specify what program to use to open the file.

pbcopy, pbpaste
Bridges the clipboard and the command line; you can pipe the clipboard into stdout, or pipe stdout into the clipboard.

ps -axww
Lists every process running on the system, and gives the full-path to them, and their PSN. I almost never use any other arguments to ps.

osascript
Execute an AppleScript. osascript -e “code-goes-here”, will execute the AppleScript inside the “”. This is a great way to get AppleScript functionality in a good scripting language.

ditto
Can do the work of cp or zip, but it does the right thing on OS X, and won’t throw away Mac-specific bits.
ditto -ckX --rsrc --keepParent path_to_a_bundledFile.bundle bundledFile.bundle.zip will compress path_to_a_bundledFile.bundle, and keep all the Mac-bits intact.

hdiutil
Create and manipulate disk-images; you can even use it to burn a disk-image to CD/DVD.
Inside a perl-script I do:
hdiutil create -ov -fs HFS+ -format UDBZ -volname \”IMLocation v$version (beta)\” -srcfolder $IMLBuildDir ~/Projects/Website/imlocation/IMLocation.dmg

To make the disk-image for IMLocation out of the contents of the directory $IMLBuildDir.

screencapture
Lets you take a screenshot. Unfortunately not very well documented.
screencapture -x /tmp/screen.png
Will silently take a screenshot, and save it to /tmp/screen.png.
I think this could be great for bug-reporting.

system_profiler
Reports system hardware and software configuration; with no arguments it reports everything. Obviously great for bug reports and research.

sw_vers
Prints version information about the Mac OS X.
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.5
BuildVersion: 9A581
$ sw_vers -productName
Mac OS X
$ sw_vers -productVersion
10.5
$ sw_vers -buildVersion
9A581

systemsetup
Configuration tool for certain machine settings in System Preferences.

defaults
Read and write application preferences. You can use it to discover and activate hidden settings, like Safari’s Debug menu. defaults read > all_defaults.txt will give you a grep-able text-file with every default on your system. It’s also a useful tool for automated testing, since you can twiddle configurations.

class-dump (3rd party tool)
Makes .h files from a binary. Great for reverse-engineering.

In addition to standard UNIX commands, Mac OS X includes many powerful command-line tools. This article only scratches the surface, and ignores many tools like podcast that are probably very useful, but aren’t part of my workflow.

« Newer Posts

Powered by WordPress