RestKit/RestKit — pull request #2071 by carllindberg (2014-10-30 06:47:36+00:00)
Title: Make RKMappingOperation be an NSObject subclass

This one is a little interesting.

RKMappingOperation really isn't used as an NSOperation; it is a utility object used for every recursive object to do the mapping. Just about all of the profiling shows methods on this class (unless you allow system libraries, at which point it is all ObjC runtime stuff at the top) when looking at RestKit/RestKit/issues/2065, so the hotspots are in this class somewhere. We really only use the cancelled status from the superclass, and the fact that -start calls -main.

So, I made RKMappingOperation be a straight NSObject subclass instead of NSOperation to see what happens. It turns out there is actually an almost 10% penalty on the entire mapping process just for having NSOperation as a superclass for some reason, at least when using a lot of nested operations such as the test app. I found the same issues in my app. I'm not entirely sure what all of the overhead could be, but it's there.

Timings before:
(Device) Mapping 5000 students with relationship mapping: 38.642747
(Simulator) Mapping 5000 students with relationship mapping: 5.517917

and after:
(Device) Mapping 5000 students with relationship mapping: 35.738455
(Simulator) Mapping 5000 students with relationship mapping: 5.000559

If we leave the superclass alone and simply override the -start method to call -main directly, I see about half the performance booth as above. So, part of the issue is whatever NSOperation does to wrap around the -main method (there will be an autorelease pool at the very least). I see most of the rest of the gain if we avoid calling the NSOperation -init method (which means we would also need to override the cancelled methods anyways, as the superclass methods crash if you call them without calling -init). I'm not sure what your back-compatibility requirements would be for this, so I would at least recommend overriding the -start method, but I'd probably try to override all the methods (trying to avoid -init) even if we leave the superclass alone. Not calling -init is a bit more dangerous though if someone calls some of the other methods. It would be safest to simply change the superclass. It does seem like a mostly internal utility class, but I may not be aware of all usages of it.