RestKit/RestKit — pull request #2085 by carllindberg (2014-11-12 17:11:38+00:00)
Title: Change the RKMappingSourceObject superclass to NSObject.

This one is a little odd, and I can't completely explain it. However, I noticed that if I changed the RKMappingSourceObject superclass from NSProxy to NSObject, there was a noticeable performance increase in the #2065 test app -- roughly 0.5 - 0.6 seconds. The testing application does not invoke forwardInvocation: at all, so it's not that (in the test app, -valueForKeyPath: is really the only instance method called). Perhaps the runtime has optimized some NSObject core methods (retain / release?) which are not as much present for NSProxy subclasses.

Most of the time, you can use NSObject for a reasonable proxy superclass. There is some risk, which is where some private categories on NSObject will no longer be forwarded but work on the NSProxy instance itself. One example was rk_classForPropertyAtKeyPath:, which I needed to implement to forward to make the unit tests work correctly. Apple does have some private __isDictionary etc. methods, for example. However, this is a private object and called under mostly controlled circumstances. During the example app, no methods get forwarded at all. During the unit tests, the only methods being forwarded (even with an NSProxy superclass) are -allKeys and -objectForKey: and those would be forwarded with an NSObject superclass as well.

I also implemented some of the other NSObject protocol methods to explicitly forward, in case those are an issue (I noticed that isKindOfClass: was being forwarded via forwardInvocation: for some reason during the test cases... odd because I thought that was implemented by NSProxy itself).

I also changed the self.object references to _object, to avoid the extra method call overhead in some of those methods, since at least -valueForKeyPath: does get called an awful lot. That seems to have squeezed out an additional tenth of a second or so. Again, as a private class, there should be no subclasses implemented which want to override the -object method, which is the usual reason why using ivars directly is a bad idea, but this class is created and called an awful lot, so it makes sense to optimize in this area.

Timings before:
(Device) Mapping 5000 students with relationship mapping: 15.597044
(Simulator) Mapping 5000 students with relationship mapping: 2.194021

and after:
(Device) Mapping 5000 students with relationship mapping: 15.021802
(Simulator) Mapping 5000 students with relationship mapping: 2.087246