Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective C Class Methods vs C Functions

While working on on open source project, I came across the following C function declaration and implementation:

// FSNData.h
NSString *stringForMimeType(MimeType type);

@interface FSNData : NSObject
// All the expected objective-c property and instance method declarations
@end

// FSNData.m
#import "FSNData.h"

// where 'type' is an enum
// this does work as expected
NSString *stringForMimeType(MimeType type) {
    switch (type) {
        case MimeType_image_jpeg: return @"image/jpeg";
        case MimeType_image_png:  return @"image/png";
        default:
            NSLog(@"ERROR: FSNData: unknown MimeType: %d", type);

        // do not return "application/octet-stream"; instead, let the recipient guess
        // http://en.wikipedia.org/wiki/Internet_media_type
        return nil;
    }
}

@implementation

// all properties and methods defined in FSData.h implemented as expected

@end

This example could easily be re-written as a class level method with out any problem. As it is, using stringFormMimeType() sill requires importing the FSNData header file anyway.

Looking at the Apple docs, it states only:

Because Objective-C rests on a foundation of ANSI C, you can freely intermix straight C code with Objective-C code. Moreover, your code can call functions defined in non-Cocoa programmatic interfaces, such as the BSD library interfaces in /usr/include.

There is no mention of when C functions should favour Objective-C methods.

The only benefit I can see at this point, is that calling the above function, as opposed to a class method, some Objective-C runtime call(s) would be skipped. In a typical use case of FSNData, this would not give a noticeable boost in performance to the user (probably even to developers)*.

What benefit exists (other than coding style) for favouring a C function over a class method?

*FSNData is used as part of the FSNetworking library, so I doubt there would be thousands upon thousands of network operations being performed during any application's life cycle.

like image 669
Mike D Avatar asked Sep 22 '13 20:09

Mike D


2 Answers

You already touched on the marginal performance difference of avoiding an objc_msgSend call. Objective-C class methods are also subject to overriding in subclasses, so implementing a method in C will prevent it from being overridden in a subclass. Relatedly, because of that runtime inheritance/polymorphism, an Objective-C method can never be inlined, whereas a C function can potentially be inlined by the compiler for added performance.

When it comes to avoiding objc_msgSend, a wise man once told me, "If the overhead of objc_msgSend is too great for you, Objective-C is probably the wrong tool for the job."

like image 162
ipmcc Avatar answered Sep 21 '22 13:09

ipmcc


In short, C (or C++) implementations are very useful:

  • For Abstraction
  • For Reusability
  • When making medium and large scale programs
  • In performance critical paths
  • For 'Interior' implementations

What benefit exists (other than coding style) for favouring a C function over a class method?

  • ObjC messaging introduces indirect function calls. These are firewalls for optimizers.
  • C functions can easily restrict access, whereas 'private' ObjC implementations may be looked up using the ObjC runtime, or accidentally overridden.
  • C functions may be removed from your executable if not referenced, or they may be made private. If you write reusable code (and you should), this can have a huge impact on your binary sizes and load times -- C functions which are not referenced/used may be removed, but ObjC types and methods will be preserved (including everything they reference). This is why your app's binary size may grow significantly when you use only small part of an ObjC static library -- every objc class in the library is preserved. If that library were C or C++, then you could get by with very small growth because you need only what is referenced. What is or is not referenced is easier to prove with C and C++.
  • C functions can be inlined, either during compilation or during Link Time Optimization phases.
  • The compiler and optimizers are able to do much optimization with C functions (e.g. inter-procedural optimizations), but very little with ObjC methods because they are always indirect.
  • To avoid ObjC message dispatch overhead (as you mentioned)
  • Potential for additional reference counting operations and autorelease pool activity when interacting with ObjC objects.

Of course you won't always hurt paying for things you don't need or use -- and remember that ObjC class methods have some benefits over C functions, too. So, just look at C or C++ implementations as another tool in your toolbox. I find them very useful as complexity and project sizes increase, and they can be used to make your programs much faster. Just do what you are least likely to regret in 2015 ;)

like image 26
justin Avatar answered Sep 21 '22 13:09

justin