NEPacketTunnelProvider causes very high energy impact in main app

Hi all,

I'm observing some strange behaviour in an iOS app that implements NEPacketTunnelExtension. I have been experiencing this for a good while now over various different iOS versions and have never been able to get to the bottom of it.

The moment the NEPacketTunnelProvider is started, my main app UI process starts getting hammered with 45% "Overhead" and 25% "Network" in the Xcode Energy Impact view and the device starts to run quite warm. CPU usage of the process is virtually zero, network activity generated by our app is virtually non-existent at the time (and Instruments supports this) and not aware of anything else going on.

We do send XPC requests to the VPN extension once every couple of seconds for a status update, but the UI has no other networking code. If we stop the VPN extension, the "Overheads" and "Network" energy impacts of the main app drop back down to normal. It's happening reliably and repeatably.

If we attach the debugger to the actual network extension PID, it looks completely normal — no high energy impact there, which makes me think this isn't being caused by our VPN extension itself. If the main app goes into the background, it gets suspended, as expected, and the VPN extension carries on with a comparatively low energy impact, as expected.

Having a hard time narrowing down what is going on here.

Any ideas?

Replies

It sounds like you are on the right track here by using Instruments to narrow down where this impacts are being incurred in your app. Based on what you mention it sounds the container app is causing these issues, so I would start profiling your container app using Allocations or Timer Profiler templates on the container app. The Allocations template allows you to take a look at a trace of your app from a thread by thread basis to see where on each thread your container app may be spending time. This would then allow you to tweak parts of your code and re-run the trace.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

Hi @meaton, I have indeed taken a look at the Allocations and Time Profiler instruments. Neither of them yield anything out of the ordinary. CPU usage and allocations look fine — pretty much completely idle when the app isn't being interacted with in fact. Despite that, the energy impact and network/overheads in Xcode are still showing very high, but only when the packet tunnel is running.

I commented out all of the code for the inter-process requests so there are no timers running or sendProviderMessage calls being made, the container app makes no network requests whatsoever and yet the problem still occurs.

If the problem is in my own code, I can't see where it is. I am wondering whether iOS is continuously sending counters/statistics/events or something from the packet tunnel back to the container app or something similar? You can probably guess from the graph for the container app when I started the VPN:

Meanwhile, the Energy Impact of the actual VPN extension process itself:

Squarely out of ideas so any thoughts appreciated!

I commented out all of the code for the inter-process requests so there are no timers running or sendProviderMessage calls being made, the container app makes no network requests whatsoever and yet the problem still occurs.

Great, thank you for ruling this out of the equation.

Regarding:

I am wondering whether iOS is continuously sending counters/statistics/events or something from the packet tunnel back to the container app or something similar?

There could be NEVPNStatus events being sent to the container app, but I am doubting it would could cause network overhead in your app. Are you observing events for NEVPNStatusDidChangeNotification?

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

There could be NEVPNStatus events being sent to the container app, but I am doubting it would could cause network overhead in your app. Are you observing events for NEVPNStatusDidChangeNotification?

Thanks for the tip. I do indeed subscribe to NEVPNStatusDidChange, although that only fires a couple of times (when the VPN changes state, as expected). I commented that out too so that we're no longer observing that, for good measure, but the problem still persists.

I commented that out too so that we're no longer observing that, for good measure, but the problem still persists.

Okay, thanks for the confirmation here. If you run out of options and are stuck on this, feel free to open a TSI and I can try and take a closer look at what might be happening. Please make sure to include a focused sample so that I can try and reproduce this on my end.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com