I would like to know specifically how impactful method swizzling is on performance. I understand it's "negligible" but what does that mean exactly? Nonetheless, I like what you guys are doing; Heap's approach to analytics its pretty clever.
There are two components to method swizzling: 1) the initial method implementation exchange, 2) the overhead of calling the swizzled method before the original method.
The actual method exchange (#1) is little more than a pointer swap and happens at load time. You can safely assume it introduces no performance overhead.
The overhead of swizzled code (#2) is also minimal. Specifically, in Instruments you'll see that ~1ms of time gets spent in an empty replacement method before the original method is called. But this replacement method is blocking, so it's imperative you keep it as lean as possible (e.g. by pushing tasks onto a background queue).
That's even better of use heap than for web pages. Usually for any web development it's so much easier/faster to deploy new version than release new version of mobile application.
Showing the CPU+Battery utilization graph for a sample app is a pretty dubious way to demonstrate the performance impacts of swizzling sendAction:to:from:forEvent:
It may indeed be a negligible impact as they claim, but using the Time Profiler instrument they could show exactly how much time is spent in the main queue on their swizzled code which would be a much better indication of whether or not the performance impact is negligible than eyeballing a cpu utilization graph.
That's true. The reason we showed the Energy Usage graph is because that's our most common perf-related question ("How does this affect battery life?").
It's certainly worth displaying the time spent in the replacement method call using the Time Profiler.
I agree with the parent. The Time Profiler data is more important in my opinion than the Energy Usage for something like this. I worry about energy usage when hardware is involved (Core Location, networking in general, accelerometer) but ideally it would be nice to see both.
Agreed. Will keep in mind next time we display performance stats.
At the very least, it should be trivial to confirm that CPU usage is low by checking out this code (or installing Heap) and running Time Profiler yourself.
In general, people avoid subclassing in Cocoa/Cocoa Touch because you often don't know the implementation of the parent class and what effect using a subclass might have (is the parent a class cluster, etc).
Many Cocoa/Cocoa Touch APIs (NSDictionary, UIButton, etc) recommend composition over subclassing, so you'll often see people do things like add a category or swizzle methods.
I've done a little method swizzling myself, but it makes me a little nervous about side effects, so I try to only use that technique as a very last resort.
I think what they're doing here is pretty clever, but I would be uneasy about using it in a shipped app.
Swizzling? Why not just override the event method in a class derived from UIApplication? That's what I do if I want to see all user events, works just fine.
Most iOS developers prefer to use composition (categories + swizzling) over subclassing because subclassing can have unexpected side effects depending on what you subclass. (I haven't tried subclassing UIApplication, so I don't doubt what you're saying at all.)
Which is fine if you're adding automatic event-tracking directly to your own app. But for a third-party library (like our own), it exacerbates the integration process. Method swizzling allows for a purely drop-in solution.
Consider that you spent over 400 words describing what swizzling is, and you likely lost a lot of audience in those vast plains of text.
For example, you lost me. Having stumbled on it, I couldn't bring myself to finish the piece. I actually do need an analytics solution for our iOS app, but this blog post just fell into "I will read it later" category, out of "I will read it now".
15 comments
[ 2.8 ms ] story [ 40.1 ms ] threadThe actual method exchange (#1) is little more than a pointer swap and happens at load time. You can safely assume it introduces no performance overhead.
The overhead of swizzled code (#2) is also minimal. Specifically, in Instruments you'll see that ~1ms of time gets spent in an empty replacement method before the original method is called. But this replacement method is blocking, so it's imperative you keep it as lean as possible (e.g. by pushing tasks onto a background queue).
It may indeed be a negligible impact as they claim, but using the Time Profiler instrument they could show exactly how much time is spent in the main queue on their swizzled code which would be a much better indication of whether or not the performance impact is negligible than eyeballing a cpu utilization graph.
It's certainly worth displaying the time spent in the replacement method call using the Time Profiler.
At the very least, it should be trivial to confirm that CPU usage is low by checking out this code (or installing Heap) and running Time Profiler yourself.
Many Cocoa/Cocoa Touch APIs (NSDictionary, UIButton, etc) recommend composition over subclassing, so you'll often see people do things like add a category or swizzle methods.
I've done a little method swizzling myself, but it makes me a little nervous about side effects, so I try to only use that technique as a very last resort.
I think what they're doing here is pretty clever, but I would be uneasy about using it in a shipped app.
Which is fine if you're adding automatic event-tracking directly to your own app. But for a third-party library (like our own), it exacerbates the integration process. Method swizzling allows for a purely drop-in solution.
For example, you lost me. Having stumbled on it, I couldn't bring myself to finish the piece. I actually do need an analytics solution for our iOS app, but this blog post just fell into "I will read it later" category, out of "I will read it now".
Noted, though, that we lost you with the piece's verbosity.