3 ms·
ObjC can be plenty fast, if you know what you're doing. And there really isn't that much to learn; it's just that most people don't learn and so they keep runni
by pjscott 3y ago
ObjC can be plenty fast, if you know what you're doing. And there really isn't that much to learn; it's just that most people don't learn and so they keep running into landmines. I'll cover the main points right now, in no particular order.
1. Allocation and deallocation involve calls to calloc/free, which are rather costly. It's easy to accidentally create and destroy an NSObject on each iteration of a hot loop. Be aware that this comes with a performance hit, and can easily come to dominate the time taken by that loop.
2. Retains and releases are pretty fast, especially on Apple's processors (which are optimized for non-contended atomic operations). However, they are atomic operations – some fancy compare-and-swap thing usually – and so you should try to avoid doing them on every iteration of a hot loop.
3. ObjC method calls are slower than C++ vtable dispatch, which in turn is slower than static function calls. Also, there's no inlining opportunity. There is caching to make method calls faster if you call the same method a lot, and the code for cache lookups is impressively fast, but if you need some code to be Fast, consider using C-style functions in critical parts.
4. When in doubt, use the Instruments profiler to find bottlenecks. It's really good.
And now a small grab-bag of more minor ones:
5. +[NSString stringWithFormat:] is surprisingly slow, or it was when last I checked. Its CoreFoundation counterpart is similarly slow. (It's the same underlying code.)
6. When you load a plist, most of which will be deallocated almost immediately, surrounding this with an @autoreleasepool block often does wonders to reduce heap fragmentation. Same goes for other operations which will tend to produce large memory spikes of objects that will stay allocated pending an autorelease pop.
7. The Accelerate framework defines a number of SIMD data types; e.g. simd_float8 is a vector of 8 single-precision floats. You can do arithmetic on them like a normal numeric data type, and the compiler will automatically emit cross-platform SIMD code. If your needs are fairly basic, this is a remarkably easy way to do SIMD programming. I've managed to get ~8x speedups with it before. (A pity that the docs are so lacking.)