System Services • 1:01:05
Join us online for a deep dive into WWDC26 with Apple engineers and designers to ask questions, get advice, and follow the discussion about the week’s biggest power and performance announcements. Conducted in English.
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it may have transcription errors.
Welcome to the Power and Performance Group lab at WWDC. My name is Cole and I’m a core technologies evangelist here at Apple. Power and performance is about getting the most out of your app, launching quickly when someone opens it. Smooth scrolling, smoothly in lists and collection views, and being optimized for battery life and storage. So today I’m joined by a panel of experts. These are just a few of the folks that work on making Apple’s own software fast and efficient, and build the tools that make it possible like instruments, MetricKit, and more.
And in addition to those on screen, there’s a whole team of folks behind the scenes helping with the triage of all of your questions. So let’s kick this off with some introductions. Maybe we’ll start with Terry. Can you just maybe each talk a little bit about yourself and what you’re focused on at Apple? Yeah. So I’m Terry. I work on performance. So I help teams across Apple optimize many of the features that were announced this week at Wwdc.
Cool. Hi, I’m Jani, I work on Metric Kit. Metric Kit is a framework that lets developers get metric and diagnostic data on device to improve their power and performance. Hi, my name is Caspar and I’m part of the instruments team here at Apple. Instruments is part of Xcode suite, and it allows you to record, visualize, and diagnose your app’s performance and power usage. I’m excited to be here. And whether you’re just starting with profiling or you would like to dive a bit deeper, I would love to hear your questions.
Hey folks, I’m Kunal, I work on power. Think about core OS power, improving the power for features, applications and optimizing them. So if you think about battery life thermals, that’s where my team really helps. And I help out with visionOS, but also iOS third party applications. Hi, I’m Marco, I’m a performance engineer here at Apple.
My main area of focus is the render pipeline Animations, scrolling, all that type of stuff. Great. Well, thank you for joining me this morning. I see already there’s a whole bunch of questions. But before we dive into the questions that we’re getting online, I just want to start with talking about the new releases. I’d love to hear. Maybe we can. I don’t know who wants to go first. I’m going to look at Casper to go first. What are you most excited about for performance in the 27 releases?
Yeah, I think that when looking at the instruments specifically, I’m really excited about the new run comparison feature. So maybe you don’t know, but you are in instruments, you’re able to record and name multiple runs depending on some of the experiments you’re running. And instead of having to have two windows side by side and comparing them visually, now you have this new Diffing feature that allows you to compare countries and understand at a glance what regressed or improved so that you can make an informed decision and iterate further. That’s awesome. How about Kunal?
I think I’m excited about definitely the tooling support that’s coming in, but also some of the metric support that’s coming in where we have state reporting and ability to kind of like slice metrics based on different application states. So we also have Xcode organizer support to kind of like have metric goals.
If you’re looking at battery life goals or your historical performance or battery life, foreground energy drain. You have this ability to now see metric goals that helps you figure out if your application is doing poorly or good as far as battery life is concerned. So yeah, lots of exciting things. And yeah.
Marco, do you have anything that comes to mind? Yeah, I’m really excited for the combination of the state reporting and the MetricKit. I feel like on the performance team, one of the hardest parts is just contextualizing what you’re looking at and like where the problem actually is. So being able to get that context of this is what the app was doing when there was a problem, kind of cuts out the whole first part of trying to triage what went wrong.
Totally. And I think, I think everyone stole your thunder here because I know you worked a lot on these changes to MetricKit, but anything that comes to mind for you? Yeah, I think I’m obviously very excited to hear that people are excited about the new features for MetricKit.
It is a very big year for us. So we have a brand new first API. And of course, like the contextualizing piece is a big help for developers to understand what’s happening in their app. So biased vote here, but I think metric features are very exciting. That’s awesome. And Terry. Yeah, I think I’m really excited about just the range of performance optimizations we’ve made across all the existing features.
I think one in particular I’m really excited about is the improvements to launch time. There are a bunch of people on my team that that directly worked on that this year, and it’s something that all apps get for free, like your app will just launch faster. And I think that’s really cool.
Yeah. That’s awesome. And to go just on the theme of MetricKit here. So I mean, we’ve kind of talked about the new MetricKit, but MetricKit is kind of getting rebuilt from the ground up. Like a lot of the existing MetricKit API has been marked as to be deprecated. There’s a new, as you said, Swift API for the framework.
Can you talk a little bit about the motivation for this change? Like that’s a big change to the framework. What is it that we’re hoping to do with the new MetricKit? Yeah for sure. So the Swift first API, of course, will work very seamlessly with Swift with Swift concurrency. So you can use a lot of our surface with more ergonomics with modern Swift apps.
Most importantly, we designed it to work very well with our new granularity in the MetricKit framework. So we’re not only are we giving developers, you know, the daily report for metrics, but we’re also having smaller breakdowns that developers can get more insights in smaller intervals. So the API is designed to sort of accommodate for these different structures and data. And as well, there’s like new diagnostic and metric types that will be only for this new API. So it’s hopefully good motivation for developers to to move. That’s awesome. Cool. Well, let’s start with our first question here.
The question that we’re getting from our online audience is, as a beginner in iOS development, what are the main factors that affect app power usage and performance in SwiftUI? And how can I design simple apps that avoid battery drain and lag? Who wants to chat about this one?
I could probably step in and start it off at the very least. Yeah, I feel like for SwiftUI, one of the main things you want to do is really separate your views from their inputs and make sure that when you’re updating variables or things are changing, you’re not redrawing stuff that doesn’t actually rely on it.
So making sure that the things that your views are looking at and watching are actually things that care about and affect the view. So you’re not doing redraws where you just end up with the same thing you had before and doing unnecessary work. So stuff like the new observable macro is really good for this, because you only get updates for the fields that you read on those objects. So you kind of get like a separation for free.
Yeah, totally. That’s a great point. And I would say that you can always understand what kind of dependencies you have using the tooling that we have in the instrument. So developers can profile their app using SwiftUI instrument. And then for the view updates, they can see show and they can see cause and effect graph that allows them to understand these dependencies and break them up as necessary.
Yeah. And to add on to the whole using instruments and stuff, I highly, highly recommend. Last year there was a talk, I believe it was like optimized SwiftUI using instruments that went through kind of a breakdown of how you can go from having an app profiling it, kind of looking at the information provided by the instrument and kind of iterating on that.
So I highly recommend checking that out if you’re interested in kind of profiling, optimizing, kind of looking at the performance of your SwiftUI app. There’s, there’s two parts that I think you’re about to say. There’s two parts to this, right? One part of this is like making sure that your SwiftUI usage is efficient. There’s another part of this, which is actually trying to figure out if there’s a power issue. And, and if that’s the case where that power issue is.
Kunal, do you have thoughts on like, where do you start for that? Yeah. And I, yeah, I do have thoughts. I think SwiftUI performance is, you know, I would say like investing in SwiftUI performance is often going to get you power wins as well, right? Because it’s compute bound, when you have compute bound operations and workloads, reducing the compute is going to help you not just with performance and latency. It’s also going to help you with power. So one of the things I would say is whatever you know, we said about like invalidations avoiding the invalidations of the views, avoiding redraws, making sure you have not a very deeply nested SwiftUI hierarchy.
I think those are all good points to not just improve performance, but also power. And we get a lot of signals for these in our existing tools, right? We have energy logs that come in for Xcode organizer that will share not just like you would often see, like these deep call stacks of SwiftUI, which could point to not just a CPU issue and an energy issue, but those same call stacks could also be seen in hangs, which is like, you know, oh, so we are not just seeing a hang because of SwiftUI taking a long time because of your UI hierarchy, but also power. So I would say go for it. You know, any SwiftUI optimization is not just going to help you with performance, but also with power.
And there’s also we talked about the SwiftUI instrument. There’s also the power profiler as well. Absolutely. Maybe could indicate if you actually do have like a CPU issue that’s landing in. Yes. That’s landing in SwiftUI code. Very good call out. Power profiler would definitely show up a bunch of the CPU energy being taken, you know, as SwiftUI rendering is going higher and you might actually see some GPU energy as well out there.
So it’s, it’s a great, you know, I would say exercise to also run power profiler with your application connected, and then look at the SwiftUI instruments and the power profiler together to figure out like what’s happening, what are the views that are causing most of the drain and the performance issues?
Yeah, and I want to add on to that. If you’re, if you’re a beginner in iOS app development, you know, maybe don’t focus too much on SwiftUI at first. That might not actually be the problem. You can profile your app using a bunch of the other things in instruments, just to see overall what is affecting performance of your app, what is using the power, things like that. If it says SwiftUI, then yeah, sure.
We can definitely follow all this advice and go down there, but it might turn out it’s something completely different. Maybe you have some, you know, algorithm that’s just churning a bunch of CPU, and that’s really where all the power drain is going. So it’s always good to just look at the overall picture first, really before diving into one specific area. 100% agree with Terry out there.
You have to understand the bigger picture. What are the bottlenecks in your application before you start investing? If you don’t do a good job at measurement, at analyzing, you might end up optimizing something that’s really not going to give you any wins or that might not be important for end users. So that’s a great point. And that’s not just in instruments too, right?
Like sometimes, and I, I’ve seen this in discussions with developers too, where, you know, you kind of think you have a problem because it’s showing up when you run it locally in instruments. And then you might look at your data in Xcode organizer and find that actually the biggest cause of, say, hangs in your app is something else. And it’s really hard to reproduce at your desk. Yeah. So, you know, kind of using both sources of data, I think is, is important. Local profiling is great for some things. Telemetry is really great for other things.
I would also say like for the power profiler workflows, maybe there’s like there’s one lesser known flow where developers can actually disconnect from instruments, go and record these traces that can take multiple hours and then analyze them at desk. So that sometimes allows them to like, hey, let’s try it out in real world scenarios and not only at your desk in a very controlled environment. That’s the.
That’s the performance trace. That’s the performance trace. So developers can capture that and later airdrop to their Mac and open that in instruments. So yeah, those both those modes, right. The tethered mode that you say where you’re actually working side by side with instruments and the untethered mode, like you said, they’re both very useful. That’s great. Just speaking more about power, we have a question here, which is what’s the biggest power mistake you see in many apps that developers don’t realize they’re making?
This is a I mean, there’s not one, right? There could be like several. And it really. Depends. That was the question. I would say one of the most common pitfalls is not having the right amount of telemetry, not having the right amount of instrumentation. Right. And so you end up focusing on areas that are not giving you the biggest return of investment.
So understanding how your application is used, what are the scenarios and features that are most heavily used by our users and instrumenting them, adding metric telemetry, analyzing them in detail, looking at field analytics, looking at power profiler or other profiling tools is a real benefit to figure out what to invest in. And people underestimate this a lot.
You know, often they might find a customer report that says there’s one specific issue and overindex on that. While there could be field analytics that’s showing a bigger problem or like a more larger set of issues. So I would say never underestimate the importance of instrumentation and measurement. You always want to measure stuff before you optimize it.
Yeah. I think, I think if I had to think of like one thing that comes to my mind, I think it’s Not accounting for different types of state that might affect the power characteristics of the app. I know we’ve we’ve both seen like, you know, you go to Xcode organizer, you look in energy logs and you’ll see things like, why is this database taking so long to write? And it’s taking so much power and it’s so much time to write this database.
And it could be because a bug is writing too much data. It could just be your app wasn’t really tested on very large sets of data, right? And at your desk, you know, connected to Xcode, you can’t necessarily replicate that. But then when you look at different sources of data, you find that that’s actually driving a huge power issue. Yeah, absolutely. Yeah. Maybe it’s part of like, part of it is also just inducing different conditions. Like maybe your device is under thermal state.
And with Xcode, you could actually use condition inducer feature to force your app in that state and then see how it behaves in instruments, like how many more hitches, how many more hangs you have so that you can, you can diagnose these scenarios. Great call out. Right. And even the untethered mode sometimes allows you to induce those conditions, like when you’re moving around, when you’re traveling and you have those cellular connections switching.
I think both of those are great ways to have those conditions induced. Yeah, we. Oh go ahead. I was just saying, I think something else that developers can sometimes take for granted is that just everything uses power. You know, every time you’re hitting the file system, you’re using a little bit more power. Every time you’re sending off network requests, you’re using more power, more precise location stuff, using more power.
So just kind of knowing what your app actually needs to be doing and how often it needs to be doing. If you can send out network network requests half as often, that’s a free power win, you know? Totally. We talked a little bit about instruments. So I’m going to pick on on this question here. The question from the developer is what is the best documentation for instruments. Are there any written guides?
Maybe I’ll look at Casper. That’s a great question. And there’s there’s many written guides, but I would say that the best one, if someone is just starting with instruments, is the instruments tutorials. So this was written a couple of years ago actually by an instruments engineer. And it was really designed to feel like you have an instrument engineer by you and getting through the app with you step by step.
It comes with an associated project that has some of the performance issues built in, so that you can just get started and learn how to, how to, how to detect Hanks. Like, how do they appear visually and then go through the whole process of profiling, fixing them and instruments.
So that would be the, the resource I would start with. And then as you’re reaching for different tools, there are guides written for them. I would also say if you’re missing any documentation, I would encourage folks to reach out to us using Feedback Assistant and let us know.
Totally. Is there any, any, maybe this is too broad of a question, but anything about instruments or maybe some of the tools that are now available in the 27 releases that are a great place to start for beginners. Like would you recommend like using the Time Profiler as your first pass, or is there something else that you’d recommend? Like if you’ve never used instruments before, start with this and give it a try.
I personally think using Time Profiler with the Flame Graph view is a really good way to start. I find that the way that flame graphs visually show you like how much a particular operation or call stack is actually costing you. It’s really easy to see like where the performance is going in your app, rather than just looking at like a textual outline or something where you have to look at numbers. Like you can just directly see like, oh, this is a really big portion of where my time is going.
Totally. Yeah, that’s a great point. And we’ve been investing in this, like, how do we make this data more approachable with top functions as well? So that’s like yet another mode of the call tree view and instruments. And that allows you to see a flat list of top helper and compiler runtime functions so that it’s easier than going through deeply nested outlines and you can see offenders at a glance.
Yeah, I the first time someone explained the flame graph to me, I was very confused about what it meant. And then I clicked it and I was like, oh, this is neat. It actually makes it pretty simple. Okay. I there’s a question here. This is kind of related to everything we’ve been talking about. The question is our app shows UIKit slash SwiftUI screens with without much background tasks, but it’s still using high battery according to Xcode. I’m assuming this is referring to the energy gauges in Xcode. What are the best practices to know what’s going on and why this might be happening? Yeah, this is an interesting one.
So the UI, we’re saying that the application shows UIKit and SwiftUI screens without much background tasks, but it’s the developer is still seeing a high battery usage in the background. Yeah, yeah. This is this could get this could get interesting. I would say like, there’s probably modes of your application where you are actually scheduling background tasks. So this may not really be to do with your foreground usage of your application.
The SwiftUI and the UIKit compute should basically reflect as foreground energy for the application. So if you’re seeing background energy drain, what you really want to look at is like, are there modes if your application where you’re scheduling background tasks or doing certain location stuff when the application is not in the foreground? And today, you know, I would say the power profiler is a great way to look at that. I would use the untethered mode often to see like, hey, are you accidentally scheduling background tasks when you’re not supposed to and profile.
That by untethered, you mean the option in developer settings. So you just like record a power trace on your device, not connected to instruments, and then exactly open that up, move around. Yeah, try to replicate a real life scenario and then see what’s really happening. And are you, are you scheduling background workloads?
So those should then be visible when you then connect and load that reason in instruments again. Yeah. That also shows you a breakdown of of energy use by a subsystem. So you can see like how much CPU, GPU display using. Maybe you’re just doing something, maybe the brightness is very high and you’re doing a lot of swaps of colors. And so there’s many, many reasons where things can be.
Networking also shows up a lot. You know, I think one of the things that you could see in the power profiler is like the network that your application is using when in the background. So yeah, these are, these would be the, the ways I would actually try to narrow in on the problem.
Excellent. Just looking through the questions here, this is a bit of a SwiftUI question, but maybe we’ll have some thoughts on it. The question is a theme object like colors and tokens is injected through environment, object and read in every atomic component. Dozens of nesting levels. hundreds of components on screen. At what scale does this become a bottleneck, and is there a recommended alternative for this use case?
Well, I guess I can pitch in on this one. It can be a little bit hard to tell specific numbers, especially because like what the actual views are can change kind of their behavior and how much of a performance impact they have. In general, putting things in the environment can be a very useful kind of abstraction for kind of passing things down through your view trees.
So I think, you know, this is probably a case where using the SwiftUI instrument, you can actually kind of see how much downstream effect these changes are costing you because it is a very case by case basis. In some cases, maybe it’s fine and it causes no issues, but there might be other kind of configurations of your views and your view tree that it might be problematic. And so really getting a view of what’s happening and what the downstream costs of those are, is really important for figuring out if it is a problem or if it isn’t a problem. Any other thoughts on that?
Awesome. Great. Let’s let’s move on to another question I’m seeing here. This one I think might be for Yani, but we’ll see how the conversation goes. How would you load large data sets like 50,000 500,000 records in SwiftUI tables? I don’t I don’t know. I know you’re not the SwiftUI expert in the panel here, but I think the interesting question maybe for you is how would you record or analyze performance and regressions using MetricKit?
So let’s say you’re trying to figure this out like, you know, how, how are you going to sustainably or scalably load this large data set in SwiftUI? How do you use MetricKit to like kind of analyze the performance? Yeah, I think I guess the first question is with a database that’s this large, how like how much of it do you actually need to load at a time for your user experience or really understanding what kind of experience you’re providing your users.
If your view is not actually showing this amount of data, the first question is, is there a particular reason why you’re loading that much to begin with? And if you’re just working with a database that’s that large, then I think, yeah, the first step of optimization is just to think about what you actually need and just load what you needed so that you don’t sort of incur, you know, work that you may not need if your users not scrolling to that view.
The other thing in terms of understanding, you know, identifying regression through metric kit or other tools, you could of course, use the new state reporting function in MetricKit that would sort of allow you to basically get information on what state your app is in, so you can better understand what is your user doing and triage. If you’re seeing a regression, what is it that is happening in your app? So you can sort of pinpoint what the problem area is.
So those would be good starting points and triaging this problem. Actually in your session video you basically talk about this exact example, right? Where you’re kind of running an experiment in the app to use like small batches or large batches in an app, and you’re using different states to get different performance metrics for those states. And then that might inform like, where do you invest more of your time?
Or how do you build out the rest of the app using that, that model? Exactly. Interesting. So would I like log my size of the list using state reporting and that would show up in metric. Yeah. So the recommendation is you shouldn’t be sort of logging very frequently changing numbers.
So like you wouldn’t be like the number of items on your list, but you can categorize them. For example, if you have a, you know, if you have, you can define what is it that like your batch size is a large size, medium or small. Then you can use that information to see, okay, within this range, my performance has been changed because like sometimes it’s like 1000 item versus 1001 item may not make a difference. But then now you’re incurring a lot of costs to like just to record that. So defining those boundaries that make sense for you to sort of analyze later will be very helpful. That makes. Sense. Awesome.
Well, actually, to, to quickly add on to the SwiftUI portion of the beginning part of the question. Yeah, please. What John was saying about the kind of batching things is really important. And SwiftUI provides some lazy versions of like stacks and stacks that will kind of manage that for you and only load things as you’re kind of scrolling and bringing them onto the screen. So you kind of benefit from SwiftUI handling that for you.
Yeah, I think, I think that’s a really important point just overall in terms of batching. And like, I know one of the things we think about for app launch time is like, what is the minimal set of information we need to draw the first frame and like, try to optimize for that to get really great launch time. And then that kind of trickles through the rest of the app to you. As you’re scrolling, you’re just kind of loading the data that that you really need. Great. I’m going to change topics a little bit because there’s a question here that I think is really interesting.
I’ll just read the question and then we can talk about it. The question is, how does iOS 27 prioritize background tasks when the system is under heavy Apple intelligence workloads? I think this question is interesting because, you know, I can totally see the concern, which is like, you know, maybe my app does processing with background processing tasks. And it’s really important that those processing tasks actually happen. Maybe my app uses app refresh tasks and I don’t want those to like go away because the system is doing more work for, for other things.
Maybe I’m looking at. Terry, do you have any thoughts on kind of like, how should we as developers kind of like reason about the new world of, of, of more intelligence features on the system when it comes to this stuff? Yeah. I think it’s a good concern to have. Definitely. And it sounds like we’re adding all these new things, like, isn’t this going to affect, you know, your apps and background tasks running on the device? I think, you know, in a lot of cases, it’s not necessarily going to cause a problem.
If you think about, you know, many of the Apple intelligence features they run on the neural engine or they’re running in private cloud compute. And so if your app is using CPU while the Apple Intelligence workload is using the neural engine, you know, those might be able to run at the same time and not cause any problem. So it kind of depends exactly on what the workload is and you know, what resources you’re actually using.
But I think in general, you know, it’s important just to make sure that, you know, you configure your background tasks into small chunks. So the system’s able to easily like pause them and resume them when necessary. So that like, if you’re doing some really big task and you have to stop in the middle, and then the next time you have to start the whole thing over again. If you’re, you know, scheduling it in chunks, then you can kind of still make progress, even though the system might not be running you as frequently as as you would hope to.
Yeah, I would say from the tooling perspective, we’ve also added some new things here for the system trace. So a new you are going to be able to see a priority of your threads. So maybe sometimes you’re mis assigning priorities on your QoS workloads or in your swift concurrency task workflows. And you will be able to see that in instruments, see what tasks preempted your thread. So this gives you more insight to to understand the exact problem.
Yeah. But I think the general thing to, to realize is that the system is, is trying to do its best to run your workloads. Even even at Apple, we have a ton of workloads that run in the background. We don’t want those to, to stop making progress either. So we’re doing our best to make sure that everything’s scheduled automatically for you and giving the best experience for the user. Totally cool. This is sort of related, but a little bit different.
This is not so much about, I think, background tasks, but kind of doing background work when the app is in the foreground. The question is to avoid blocking the main thread. I perform expensive tasks on background threads. However, during launch, this method causes a lot of thread hops. And there’s kind of two questions here. One is how expensive is frequent thread hopping as compared to thread blocking? And the second is, is there any better solution overall for performance?
That we’re all looking at each other wondering who wants to talk first? I guess I’ll start with the specifically about the thread hopping. Yeah, it’s certainly a concern. You know if you’re doing it way too frequently, it will add overhead every time it has to switch to a different thread. But in general, if you’re not doing it a whole lot, like the overhead is pretty much negligible.
So, you know, I don’t know of an exact number, but I would say, you know, if you’re not doing it like thousands of times per second or something, then it’s probably fine. And then, you know, one technique you can use is, is also if you can wait to do some of that work as well.
A lot of that work is not necessarily needed. Exactly. At launch, we just talked about this in one of the previous questions. You know, think about what is the data you need, the minimum amount of data you need to get your app to its loaded state during launch.
And then you can kind of, you know, delay everything else until after that has already happened. Also, you know what Casper mentioned earlier for the background tasks, making sure we’re prioritizing things correctly as well. That’s really important. So, you know, all those background threads that maybe you’re spinning up as long as they’re prioritized, you know, lower than the work that your app is actually doing to load its main content, then it hopefully won’t have too much of an impact on what the user is actually experiencing.
Yeah, that’s a great point, Terry. I think the lazy, you know, deferral of work, the non-critical work, I think that is a key to make sure your launch is really, really optimal. So there’s other techniques as well, right? I think there’s prewarming of the application. Like if you have abilities to use BG app refresh task to actually fetch the information that’s needed during the launch, you’re, you know, you’re reducing some of that workload when the launch actually happens. So keeping a really close eye on what’s really needed and what can be deferred or done earlier is really a good way to minimize those context switches during the app launch.
And what would be like the approach to kind of see if this is a problem? Like how do you what’s the best way to like measure this and see like, is this a theoretical problem or is this an actual problem? And the instruments, you will see a context switch count being graphed as a histogram. So that can give you an idea on how many context switches are happening. And you can try to correlate it with your app launch metrics, for example. So maybe you’re trying different approaches and one of them context switch count spikes and see how that affects your your app launch.
But yeah, I definitely agree with the points made that try to defer the work. And I think that sometimes we see developers trying to fetch kind of like a B test experiments during launch, things like that. Or, and yeah, I would say maybe, maybe you can just cache the last result and change your business logic this way. So try to try to be creative about this.
Yeah. I think you folks can keep me honest on this, but like, I think the bigger issue that we’ve seen across apps is not so much spinning off work. I mean, it can be a problem. I’m not saying it’s not, but not so much spinning off work that needs to be done on different like background queues. But it’s often the case where you spin off a whole bunch of work, and then you make the main thread wait for all of that to complete before your first frame.
Because now, now the whole app is basically frozen until that that background work is complete. So maybe this is like a tangential, tangential question. What’s the best way to identify that? Like, how do I know if like, it’s my problem isn’t so much that the background work is happening, but it’s actually delaying my app launch because of all that work.
I mean, if you’re actually waiting on that, you would see it in the main thread view in the instrument. So you would use system trace, a template that allows you to record all of your thread states. And in this case, your thread probably would become blocked. Like if someone is actually is actually blocking their main thread.
So you would, you would look there. But yeah, I can definitely see, I think very common case is like spawning too much background work during launch and that is competing. And maybe you have your network request and a couple of other requests happening at the same time, maybe from some framework that you’re linking. So really inspecting what’s happening and what’s on your critical path to launch.
Gotcha. I think Sorry. Go ahead. Sorry. I think the one of the sort of more out of the box sort of like way to think about this is also just if you’re not even checking your launch time, I think a good starting point is to even look at your launch time to begin with. Like, what is your launch time?
Like? What do you think about like, how does that align with what you expect? Like if you’re the user and you’re waiting this amount of time for your app to launch, how like, what would you think about that? And then using that sort of metric to compare with different versions of your app to see if that has moved and how like, is that expected? Or are you, did you make a change that you need to sort of address this issue?
Yeah. And then the other thing I wanted to add was, if you have already shipped your app out to customers and they’re actively using it, you might be able to open up Xcode organizer. And there’s a launch area in there as well, which shows you not only the launch metrics, but also it can show you the top issues of the actual call stacks where users are hitting slow launches. And so in that case, without even profiling. Profiling with instruments, you’ll still get a similar view. And you can see if your app is blocking on other work or just doing too much CPU work during launch.
Totally. Great point. I actually just just talking about app launch a little bit. I’m remembering a question we got in the labs yesterday at Apple Park around just measuring app launch time, because I think there’s a lot of folks that come up with kind of their own technique. They might be inspecting like kernel APIs to see when the process was created. And they’re using that as one of the kind of goalposts for, for, for launch. But MetricKit doesn’t do that at all.
Right? It uses a different technique for actually measuring launch. Do you want to talk a little bit about that? Yeah. So we obviously recommend the Apple Technologies for folks to measure launch and don’t try to sort of speculate or inspect and cause actual more overhead in trying to get this information.
I think if you use metric or the organizer, you would get this information. The system would do that for you. It measures, you know, when the user taps on your app and when your app actually launches, where the first sort of like, you know, first screen is drawn. So all of that is done for you at a efficient way that will not incur extra costs to your app.
So definitely recommend using our tools. That’s the same thing we use for our own apps, right? When we’re measuring launch time for like the mail app, for example. Yeah. Yeah. And I think that what’s really cool about that is that like, it measures something that you can’t measure inside your app process, which is like when someone actually taps on your app icon on the home screen, like your app is far away from existing yet and yet MetricKit and the organizer are able to kind of give you that interval, which is, which is really great.
Exactly. Okay, I’m going to go back to some of the questions we’re getting here. This question is kind of going back to battery. I know we touched on this a little bit already, but the question is besides background tasks, what’s the most common silent battery killer in SwiftUI? How much power does view over invalidation actually drain? And what’s the best instruments workflow to catch it before release?
Yeah. I mean, do you want to. Sure. I’ll I’ll hit the SwiftUI side of it and then you can go for the power stuff. I mean, yeah, view invalidate view over invalidation can be like a very big killer of battery life just because you are just redrawing, doing a lot more work on the CPU.
And also it is like a very silent thing because by definition, over invalidation is you are recreating a view that looks exactly the same. So you could be looking at your phone and you can see nothing’s changing on screen, but in the background, if you’re over invalidating, you can have the CPU just churning and churning and churning.
Yeah, completely agree with you. I think for SwiftUI, I would just mainly focus on minimizing the redraws and maybe flattening your UI hierarchy as well. I think that’s a big one. These should help minimize your foreground energy drain quite a lot. And then looking at other, you know, like other work that you’re dispatching on the background threads, those could be other aspects, you know, that are happening, that your SwiftUI, SwiftUI threads are dispatching workloads in order to kind of get information, fetch data so that they can show it.
Keeping a close eye on that is also useful, like caching, you know, using the basic principles of software engineering cache when possible, you know, minimize repetitive work. I think those are all the things that you should focus on. And I would say as far as our tooling support is concerned, SwiftUI instruments is a great way to actually focus on those.
Gotcha. Just kind of on the topic of, of SwiftUI, there’s a question here. And I, I know you folks are not the SwiftUI engineers, so maybe this is a question better suited for our SwiftUI group lab, but maybe you folks have thoughts anyway, are there any performance improvements for very large lists and table views in SwiftUI for macOS. 27. What are some best practices for making long SwiftUI lists and tables work well with tens or hundreds or thousands of items. Do you have any thoughts on this, Marco?
Yeah, I mean, I think for having like large lists and stuff like that, one of the things is like, if you’re keeping your list size constant, then SwiftUI can kind of know how to manage it. Whereas if you’re kind of constantly changing the size of your list, that can change like the height of things.
And like, as long as you’re keeping things more or less constant, that works pretty well with Swiftui’s model of kind of updating things as needed. And there are some like lazy data structures and stuff that can kind of help you. And then also moving some of that kind of filtering and stuff into the kind of model side of things.
So instead of having like an if statement in your foreach, that is checking each thing in your list and like having to do that calculation. If you do that before you even provide the list to SwiftUI, then SwiftUI doesn’t need to kind of like chew on that. It can just display what it needs to display, nothing more. Are there any any other kind of kind of sources of hitches that you’ve seen with like very long listen tables apart from just like, kind of like you said, batching it in the model, is there anything else that people should be like on the lookout for?
I know that’s like a broad question. Maybe the answer is no, but. It it’s kind of tough. Yeah. I mean, I think a lot of the things, it’s like when people have cells inside of their lists that are changing size, it kind of has a cascading effect where, you know, if something in the middle list changes size, suddenly everything below it has moved.
And we have to do recalculations of knowing like what would be on screen at this kind of offset in the scroll view. So we kind of have to do more work to figure out like, okay, what state are we in now versus, you know, keeping things very similar, clean, tidy, constant size where Swift can kind of utilize its kind of caching capability that it uses behind the scene, I think is very important.
Gotcha. Great. And on the kind of similar topic of SwiftUI, this is a fairly advanced SwiftUI question. But the question is I use any view for type erasure in several places. How expensive is it in practice? Is there a concrete threshold like in views and redraws, beyond which any view becomes a problem? Or is avoiding it premature optimization?
I’ll take this one too. Sure. So using any view and using type erasure does add a bit of overhead when you’re creating the view. And I would try to avoid it if you can easily avoid it. However, I do think it’s one of those things where you can address it if it becomes a problem. I think trying to kind of bend yourself around, not using it.
You’re kind of missing a return on investment. And if it becomes a problem, you can maybe keep it in mind as something, as a, you know, on the roadmap of maybe this will be a problem. But I think trying to focus on that. I think there are probably time better spent elsewhere. Yeah, I think focusing on measurement, not only in SwiftUI.
I feel like when I’m working on instruments itself, and sometimes I have a need to make something threadsafe and add unfair lock, for example, I have a perception of like, oh, it’s going to be really expensive, but then I add it and it’s just so quick. So I really base your actions on the measurements.
Yeah, I think that’s important too, because like, we try really hard not to build API that are like a rake to step on. Like, you know, certainly there are, you know, patterns that work better than others. I’m not not saying otherwise, but for example, I’m thinking about there’s an accessibility session this year that talks about using any layout to switch between a horizontal layout or a vertical layout, depending on if you have larger text enabled, that’s totally fine.
Like that’s probably you can measure it, but that’s probably not going to have this huge performance impact, but you could totally go overboard and do something that might have impact. So I totally agree. Measurement is kind of the best best place to start. Yeah. And the features are there for a reason, right?
If they are more expensive, like sure, you might need to take that cost and that’s fine in a lot of cases. Yeah. Great. I’m going to move on. Let’s this kind of switching gears back to MetricKit and state reporting. The question is MetricKit. State reporting and crash report extensions are new and noteworthy this year.
Are there any other headlining developer tools that didn’t make the updates page on the developer site worth looking at? I know we talked a little bit about some of our favorite things this year, but anything come to mind that maybe we haven’t talked about yet? Yeah, I think there’s a lot going on with Xcode organizer. So it does provide field data like MetricKit. It, it is a different population that is aggregated across all of your users.
It does provide like a visualization, but it has less flexibility in terms of how you want to aggregate data compared to MetricKit. So some of the very exciting things, because it is aggregating across different apps, we do have improvements in metric goals. So developers can actually get a bit more guidance in terms of how you’re performing compared to apps that are compared that are comparable to your app. So this helps with forming a baseline, which is a very hard thing. If you’re just given a number. How am I supposed to know? Is it like doing okay? Is should it be better?
So I think that is a very helpful way for developers to, if you’re just starting out and you haven’t been measuring out of the box, you kind of already have a guidance line there. I think, I think this is so neat because I think one of the questions we get in the labs all the time is folks open up their Xcode organizer and show it to us and say, I’m a video app. I play video all day long. My power is through the roof, I think maybe, or is this fine? I don’t know, right? Like, what’s a video app supposed to use in terms of power. So now you get that.
You can actually see compared to similar apps, what what’s their performance look like and kind of make decisions based on your stuff. Exactly. Any other, any other kind of tools of thoughts on the new stuff? Yeah, I think like what I didn’t talk about things like foundation models.
So for example, Foundation Models has a new updated tool and instruments. And this year it’s extending. So last year we’ve had just some basic metrics on the tokens on the token counts. Right now it’s a fully, fully debugging tool that allows you to inspect all of your requests prompts, understand how many tokens are being cached.
So if you can, if you want to look into the performance side of things, that’s, that’s going to be your, your great tool for that. There’s also a tool that’s shipped in 26.4 for profiling long term metal apps. So we actually didn’t talk about it. There’s a dedicated session, but this tool allows you to record performance of your game over hours and understand FPS metrics, understand the outliers, and burying it. For example, with the state reporting would allow you to maybe see maybe you are dropping frames in a specific level and inspect some of these workflows. So I would I would recommend the sessions for checking these workflows out.
That’s awesome. What else? I think the other thing that I would point people to is there’s a post on the developer forums that is, I believe in the metricate tag that talks about kind of all the new stuff. So if you haven’t been taking active notes throughout the group lab, you can check out that forum post. It’ll redirect you to, to all the new stuff that we have for, for perf and power this year.
Great. I guess here’s a question. I guess if knowing the new tools that are out there, if there’s kind of like one thing you think you know, you would encourage developers to like, go check out for their app as kind of like a homework assignment from, from all the new stuff that they can do this year. What’s like for you? The one big thing that you want folks to, to give it a, give it a shot before they wrap up their Wwdc work.
I mean, I can take that one. Go for. It. I think definitely looking at metric goals is a big one, right? Because now you’re going to see the metric goals and compare your metrics, how they’re doing with it. So similar applications and having a sense of how similar applications are doing against your metric is a great way to understand what areas you need to invest in, whether it’s power, foreground, energy launches, hitches, hangs. So that would be one big point. And then the second one I’m going to give a shout out to is the state reporting.
I think it really allows you to slice the data and figure out in what application states are your, Are your metrics doing poorly? So if you’re using a combination of metric metrics along with state reporting, I think you can zoom in on the specific areas in your application that need attention. So yeah, those two things. Awesome.
I’m going to take a question that’s a little bit different. So the question reads, Swift performance is something I’m genuinely passionate about and want to go deep on beyond Wwdc sessions and swift evolution proposals. What is the pathway look like? Specific code bases to study compiler internals. Books, benchmarks for building real, deep expertise in this area.
I think the when it comes to like understanding not just Swift and SwiftUI, but like any kind of technology, I think it’s just experiences kind of king here. Yeah. And I think that like, given all the views and perspectives that instruments, tools provides, like there’s so many different templates, like the Time Profiler, SwiftUI instrument and all that stuff that like just building things out and looking at them from that point of view and seeing what’s actually happening and going on can kind of give you a better grasp of mental model on like what these frameworks are doing behind the scenes. So I think just trying things out, opening it up in instruments, trying out different templates and just seeing what it looks like when you do certain things can be a really good way to just kind of really immerse yourself, basically immersion, right? Immersive learning.
Yeah, that’s a great point. And I think that from the resources that Apple provides, we have had optimized CPU performance with instruments last year. And that was a fantastic talk that went a bit deeper and it covered not only time profiler, but also CPU profiler processor trace so that you can get the full overview of the suite for, for CPU usage. And there’s also Apple Silicon optimization guide that allows you to understand like how really things work under the hood so developers can check that out. Awesome. Anything to add?
Yeah. I’m just going to echo the Apple Silicon Optimization guide. I think one really important part is like really understanding how our CPUs and our hardware works. If you have a really great understanding of that, then you can really take advantage of actually implementing swift algorithms and things like that, which will perform really well on, on Apple hardware.
That’s great. Okay. This kind of goes back to SwiftUI a little bit, but let’s let’s take a look at this question. So the question is, so this person attended the one of our performance events in October and learned to avoid kind of escaping closure based parameters because closures are hard to compare. And that makes SwiftUI do more view and validations.
The question is it’s been limiting because they’re having to pass viewbuilder content itself, whereas sometimes passing in an escaping parameter is essential. This also might be a question better suited for the SwiftUI Group lab, but any any thoughts on kind of like, you know, how to architect SwiftUI in, you know, trying to avoid escaping closures that could cause performance problems.
So I think like calling the closure in your init rather than like in the body of the view so that it doesn’t just run every time the view is reevaluated can be a good thing. I don’t know a ton about this area, but then I think in general also, like if you’re finding that closures are causing a performance issue, like maybe there’s another API or a different kind of like structure that you can use to kind of get the same functionality without the same kind of performance hit of using a closure. But yeah, I’d highly recommend the SwiftUI group lab. I think tomorrow at 9 a.m. is. I think that’s right. It’s online. You can check the schedule. Awesome. Anything to add?
All right. Okay. this might be for both Marco and Kunal. The question is, this is a beginner developer, a mom of nine, former nurse, getting back into tech when handling dynamic data or heavy assets in SwiftUI. What are the best practices for ensuring view updates don’t cause performance stutters like hitches or high CPU spikes on older devices?
I mean, I think for stuff like heavy assets, I think there is something to be said about like kind of tailoring what assets you’re using. Depending on the use case, for example, you don’t need like a 2000 by 2000 pixel image if it’s just going to be a thumbnail. So I think making sure that the assets you’re using are properly suited for the use case can be very important.
Do you have thoughts on like, like CPU spikes? Like what? How do you kind of detect when those things happen and if they’re bad, and if you need to do something about it? Yeah, I would say assets. And, you know, like in general loading data, especially during launch times or, you know, when you’re showing a new page, initializing a view, paying attention to not just what Marco said, which is like, hey, minimizing the resolution or like having the, the, the most lean weight version of that asset is very useful.
But then there’s another thing like caching. I think caching is a good one. Once you’ve actually shown that asset, just making sure that you have a cache that can be accessed again and again would really help with minimizing some of the CPU workloads that can happen by either processing or parsing the network. Call that fetch the data.
So being mindful of, you know, making sure that the assets that you’re sharing are lean as well as that you’re not refreshing them or recomputing aspects of that asset can be, can be very useful. Something else to add actually is that oftentimes if this asset is not load bearing in your application, then you can do something like, you know, put a placeholder image up or like a loading placeholder thing.
So that way you don’t have to load the image on the main thread and the rest of your app can kind of continue on and do its work while the image gets loaded in the background, I think can also be very good for kind of performance. Yeah, yeah. Perceived performance and kind of that responsiveness feel like.
Yeah. What about the, the aspect of this question that’s around like older devices, like if you have a newer device and you’re, you know, you’re an independent developer and you have a newer device and you want to make sure performance is good on older devices, but you don’t have one. Like any thoughts on how you would kind of get a feel for if you’re having this problem there?
I think one really easy thing you can try, even if you have a newer device, is just turn on low power mode. Okay. You know, because that that makes the CPUs run a lot slower to save battery, but it also means you might encounter some issues that you wouldn’t normally see if you weren’t in low power mode. And those might be similar issues that you would encounter on an older device.
And it’s also just a great way to generally optimize your app. Lots of users love low power mode. And so they’re going to have it enabled. And if your app doesn’t feel great in that mode, then you should definitely look into optimizing that. And there are also condition inducers that I mentioned.
I would also say that we see developers profiling on simulators. And yeah, there’s no difference depending on which simulator to you use on what performance do you get because it all runs on your Mac. So that’s, that’s one thing that is so I would recommend just always use a physical device, a physical device for profiling specifically. I think another note is because physical devices are sometimes harder to get as a developer.
Tools like, you know, like MetricKit and organizer will allow you to give, get field data, which you would have a bigger data set from your users. So if you naturally have users that have different types of devices, different conditions, those would be really good ways for you to get information on your CPU usage on a larger data set in real environments. I want to talk about this. You mentioned the condition inducers a couple of times. Can you just say more about what that is like?
How does it induce a thermal condition? Does it make the device hot? Like know what’s going on? Not true. Not truly. That just artificially induces that. And that’s a feature that is part of Xcode. So developers are able to start a debug session or I believe it might be, I’m not sure it might be in the new device hub.
They are able to put their device in an artificially state, and they could limit things like network speed and other variables. Gotcha. So it is it is reducing CPU and other things. It’s just it’s it’s simulating what would happen if the device were warm. Got it. Okay. Well, since we’re talking about power, I have another question here. That’s that’s kind of along the same lines, the the question is our app heavily relies on AR kit, metal and other compute intensive processing since it is primarily used outdoors in direct sunlight.
Other devices frequently experience elevated thermal states. What are the recommended strategies for managing thermal pressure and preserving a good user experience? Yeah. I sympathize with an app that’s used in direct sunlight all the time. I. Yeah, it’s a challenge. What? Yeah. One of the things I would definitely advise is there is an API out there that’s, you know, like indicates when you’re running into like the higher thermal states. Yeah. So make sure your application is listening for that. There’s the process info the thermal state. Go ahead and make sure your application is able to listen to higher thermal states.
And based on that back off on the experience. Right. I think if there’s often experiences can be designed in a way that they need. They don’t have to be rich all the time. You can back off of some of the richer experiences without significantly compromising the end user experience. So looking at those thermal states is a good way to, you know, avoid such situations. Yeah. Do you have examples of like what you could back off? Like, is anything like maybe non-obvious that someone could do to back off the work in thermal pressure?
Yeah. I think this is like pretty case by case, right? It would really depend like, for example, let’s say you had heavy assets that you were downloading from the network that result in heavy parsing times, right? And like a lot of decoding that’s happening on your device. Now, one of the things you could do is in your heavier thermal state, you could actually make those HTTP requests and request for more lighter resources from, from the network so that you’re not going to be spending a lot of processing time on your device. There’s other things you could do, like if you have heavier animations or more richer, smoother transitions, you could like back off on those and have more simpler navigations or simpler animations.
It’s case by case. Actually, I think that the frame rate thing is actually pretty cool too, right? I think we’ve seen that strategy in a lot of cases where you just reduce the frame rate and, and until you exit that, that pressure condition. Yes, that, that, that one definitely helps. And often the system can also like in heavier thermal states, the system also puts in certain mechanisms to minimize animation frame rates as well as like display frame rates. So there’s some benefit you get just by default. And then you can add on top of those.
Gotcha. Any other thoughts on on kind of thermal conditions? Yeah. I mean, just to like, yeah, frame rate kind of backing off on frame rate stuff like backing off on resolution. So if normally you’re running at a high resolution, you get a thermal state indicator. That might be a good time to kind of lower the resolution, you know, pushing less data around less pixels, it’s going to be less work. And ultimately, at the end of the day, you’re just, your app is in a use case where you kind of have to keep performance in mind, and you just have to optimize your app in that case. There’s no getting around thermodynamics.
Well, and I think that’s the interesting thing about this problem is that like, there’s a part of this that you control, which is your app and the compute that your app needs and the power draw that your app needs. There’s a part of this you don’t control. Like ultimately, you know, devices can’t run at 100°C. It doesn’t, doesn’t work. So so there’s an aspect to this, which is like, optimize the heck out of the part that you do control. And, and that’ll give the best possible chance that someone in those conditions are going to be able to, to use the app.
Great. I think we have time for maybe one more question. I’m just going to peruse here a little bit. Let’s look at. I think we talked about the environment briefly. So maybe this will this will be somewhat quick. But the question is does using a lot of environment properties in a large SwiftUI app have any performance impact. For example, if many values are injected into the environment across a deep view hierarchy, does that affect rendering or update performance in any way?
So for the environment, the biggest thing for performance and kind of all that stuff is environment churn. So if you’re just putting values in the environment and reading them out of your views, it’s not that bad. It’s not that expensive. It’s when you start kind of like updating those in a high frequency and causing environment churn, because other views that are reading from the environment now have to reevaluate, like has something in my environment changed? So putting things in the environment is not necessarily that expensive, but it’s when you start kind of like really churning the environment that that’s when you start to run into issues.
Gotcha. And of course, you could see this in the variety of instruments we talked about, like the SwiftUI instrument today. Absolutely. That’s great. Well, I think that’s about all the time we have for this group lab. We’re so thankful that you joined us today and hope that you found today’s conversation helpful.
Thank you to all of our panelists, as well as the folks behind the scenes working hard to make today happen. If we didn’t get to your questions, please visit the Apple Developer Forums at developer.apple.com/forums, including the Power and Performance Q&A, which is taking place on the forums on Thursday at 10 a.m. Pacific.
And of course, if you have any feedback or bugs, file [email protected] and you can also try out the new generative AI search [email protected] to get answers about frameworks, design accounts, and everything related to development on our platforms. And speaking of feedback, you’ll receive an email with a survey link to let us know about your experience at WW DC. We would love to incorporate your feedback in future events. Thank you so much for joining us today and have a great Wwdc.