Instruments

RSS for tag

Instruments is a performance-analysis and testing tool for iOS, iPadOS, watchOS, tvOS, and macOS apps.

Instruments Documentation

Posts under Instruments tag

95 Posts
Sort by:
Post not yet marked as solved
1 Replies
330 Views
Hello everyone, Our iOS app is taking too long to launch. On checking the launch profile, we are seeing that most of the launch time is being spent in applying fixups which is taking more than a second and at times even more to complete. Our deployment target is iOS 15+. We have checked using dyld_info that our binary uses chained fixups. Since chained fixups are enabled, page-in linking should also be enabled for our app as per this WWDC session. Can someone please help us understand why the fixups application is taking this long and how can we improve it? Thanks.
Posted Last updated
.
Post not yet marked as solved
2 Replies
303 Views
I am using the Leaks instrument, and it has identified a bunch of 32 and 48 byte "Malloc" leaks. I would like to see a hex dump of some (or all) of those areas. I think if I can see what is in them I can get a better idea about what is triggering the leak. I'm pretty sure it is a real leak. What is the easy way to do this? Can it be done inside instruments, or do I need to run my app under instruments and also attach via lldb and hexdump from lldb? (can I attach lldb and instruments at the same time?) If it matters I'm debugging an iPadOS app, and it is written in Swift plus ObjC, plus ObjC++, oh, and some straight C++.
Posted Last updated
.
Post not yet marked as solved
5 Replies
882 Views
When using Instruments in Xcode 15.3 on macOS Sonoma 14.3.1 symbols from system frameworks are not displaying. I've tried creating a template "App" project and running it on the iOS 17.4 simulator without any code changes and still am not seeing symbols so I can be sure it's not unique to my real-world project build settings. If I install Xcode 15.0 and run the same build in the same 17.4 simulator using Instruments 15.0 it shows thread names and symbols for UIKit and other frameworks but is still missing SwiftUI symbols. Instruments 15.3 Instruments 15.0 I've spent 2 days trying to narrow down why I couldn't debug my app and even deleted all my partitions and reinstalled macOS which didn't fix the issue.
Posted Last updated
.
Post not yet marked as solved
3 Replies
636 Views
Hello, This relates to NSTrackingDomains for Privacy Manifest. Following doc here https://developer.apple.com/documentation/xcode/detecting-when-your-app-contacts-domains-that-may-be-profiling-users. (Also, I'm quite new to using the Network Instrument). I'm not seeing any "Points of Interest" but I know my app has domains that should be shown as "Faults". Do I need to os_log to my Objective-C codebase. I don't have access to the code of various 3rd party SDKs. The doc mentioned above made it sound like these domains should automagically appear. Thanks!
Posted Last updated
.
Post marked as solved
10 Replies
1.9k Views
I have a performance issue with a Mac SwiftUI app. Using instruments I see hangs reported. When I zero in on a hang I see that the time profiler reports most of the hang -- in one example 658 out of 687 ms -- being in 'static AppName.$main() [inlined]'. I think that is saying my app is busy, but busy doing what? The "hangs" are related to SwiftUI table processing. User experience is something like this: select an item, see the view changes based upon selection show up a second or two later. The duration of the hang increases with the number of items in the table. I'm testing with 100 ~ 1200 table entries.
Posted
by marchyman.
Last updated
.
Post marked as solved
3 Replies
453 Views
I have an iOS app that uses os_signpost API for instrumentation. When I profile it from Xcode on real iOS device, it works as expected. When I profile its macCatalyst variant (using the identical code) on the same Mac where Xcode is running, the os_signpost Instrument does not show anything, not even the Apple provided signposts that are otherwise visible on the iOS. How do I make it work?
Posted
by enodev.
Last updated
.
Post not yet marked as solved
10 Replies
1.1k Views
Hello, I am trying to debug Swift Concurrency codes by using Swift Concurrency Instruments. But in our project which has been maintained for a long time, Swift Concurrency Instruments seems not working. Task { print("async code") await someAsyncFunction() } When I run Swift Concurrency Instruments with the above codes in our project, I could check that the print works well by checking stdout/stderr Instruments, but there are no records on Swift Concurrency Instruments. But in the small simple sample project, I checked that Swift Concurrency Instruments works well. Are there any settings that I need to do for the legacy project to debug Swift Concurrency?
Posted
by presto95.
Last updated
.
Post not yet marked as solved
9 Replies
4.7k Views
Hi, I've run an Instruments network capture of our iOS app and the Points of Interest track lists faults due to undisclosed tracking domains. For example app-measurement.com which is used by Firebase causes the fault: Fault: app-measurement.com is not listed in your app's NSPrivacyTrackingDomain key in any privacy manifest. It may be following users across multiple apps and websites to create a profile about users of apps that contact this domain. However my PrivacyInfo.xcprivacy file contains (API and Nutrition info omitted): NSPrivacyTracking: true NSPrivacyTrackingDomains: app-measurement.com So I'm surprised the fault is still occurring. Is it because the call is coming from a 3rd party SDK (Firebase)? I'll be removing this entry once a compliant Firebase SDK is released but figured it should still work. I've checked that the IPA contains PrivacyInfo.xcprivacy, and that I'm able to generate a privacy report. I'm using Xcode 15.0, iOS 17.1.
Posted
by sbenfold.
Last updated
.
Post not yet marked as solved
1 Replies
457 Views
I'm introducing some SwiftUI into a primarily UIKit app and have noticed that, as soon as a SwiftUI view is presented / pushed to the nav stack in its hosting view controller, the memory graph shows a number of Swift closure context (unknown layout) entries under an <unknown> header. These entries persist after the SwiftUI view has been popped from the navigation stack. Is this cause for concern? I don't think it represents a memory leak within my app, because the entries are grouped under <unknown> as opposed to my app name. But I'm not entirely sure why they exist (and crucially, why they persist). It's possible to observe this behaviour with a really simple demo app. Just push the following view: struct ViewController02: View { var body: some View { Text("Hello, world!") } } onto a navigation stack: self.navigationController?.pushViewController(UIHostingController(rootView: ViewController02()), animated: true) Any advice / guidance / reassurance would be much appreciated. There can be a considerable number of these entries but I can't see how I could be causing a retain cycle.
Posted Last updated
.
Post not yet marked as solved
0 Replies
262 Views
Hi! Is there a reason why trace's *-profile tables (time-profile, cpu-profile, counters-profile) always use an instruction pointer value that is 1 byte larger than what should be a true instruction pointer value? Odd valued IPs on Apple M2 are definitely incorrect as instructions have to be word-aligned. It's also worth mentioning that addresses in "source" tables ("time-sample" for "time-profile", "kdebug-counters-with-pmi-sample" for "cpu-profile" and "counters-profile") are correct (or, at least, are correctly aligned aligned). Here's an example: % xctrace version xctrace version 15.2 (15C500b) # run recording % xctrace record --template "Time Profile" --output TP.trace --launch /bin/dd if=/dev/random of=/dev/null bs=1024 count=1048576 # extract "source" table % xctrace export --input TP.trace --xpath='/trace-toc/run[1]/data/table[@schema="time-sample"]' > tp.time-sample.xml # extract "derived" table % xctrace export --input TP.trace --xpath='/trace-toc/run[1]/data/table[@schema="time-profile"]' > tp.time-profile.xml % xmllint --xpath '//row[1]' tp.time-sample.xml <row><sample-time id="1" fmt="00:00.040.502">40502000</sample-time><thread id="2" fmt="Main Thread 0x37c2d0a (dd, pid: 32471)"><tid id="3" fmt="0x37c2d0a">58469642</tid><process id="4" fmt="dd (32471)"><pid id="5" fmt="32471">32471</pid><device-session id="6" fmt="TODO">TODO</device-session></process></thread><core id="7" fmt="CPU 4 (P Core)">4</core><thread-state id="8" fmt="Running">Running</thread-state><sentinel/><kperf-bt id="9" fmt="PC:0x1863149fc, 3 frames, 1 regs, pid: 32471"><text-addresses id="10" fmt="frag 1717">6546645708 6546360308 0</text-addresses><text-address id="11" fmt="0x1863149fc">6546344444</text-address><process ref="4"/><register-content id="12" fmt="0x2e4c00018635e2cc">3336041430521340620</register-content></kperf-bt><time-sample-kind id="13" fmt="Timer Fired">0</time-sample-kind></row> % xmllint --xpath '//row[1]' tp.time-profile.xml <row><sample-time id="1" fmt="00:00.040.502">40502000</sample-time><thread id="2" fmt="Main Thread 0x37c2d0a (dd, pid: 32471)"><tid id="3" fmt="0x37c2d0a">58469642</tid><process id="4" fmt="dd (32471)"><pid id="5" fmt="32471">32471</pid><device-session id="6" fmt="TODO">TODO</device-session></process></thread><process ref="4"/><core id="7" fmt="CPU 4 (P Core)">4</core><thread-state id="8" fmt="Running">Running</thread-state><weight id="9" fmt="1.00 ms">1000000</weight><backtrace id="10"><frame id="11" name="0x1863149fd" addr="0x1863149fd"><binary id="12" name="dyld" UUID="324E4AD9-E01F-3183-B09F-3E20B326643A" arch="arm64e" load-addr="0x186313000" path="/usr/lib/dyld"/></frame><frame id="13" name="0x18635e2cc" addr="0x18635e2cc"><binary ref="12"/></frame><frame id="14" name="start" addr="0x1863187f4"><binary ref="12"/></frame></backtrace></row> As you can see, <kperf-bt id="9" fmt="PC:0x1863149fc, 3 frames, 1 regs, pid: 32471"> refers to a properly aligned address, but the address from <backtrace id="10"><frame id="11" name="0x1863149fd" addr="0x1863149fd">... is off by one. It seems like only an address from the top frame is incorrect, as others are aligned properly. The same issue exists for "CPU Profile" and "CPU Counters" instruments and could be reproduced on macOs running on both x86-64 and Apple-Silicon CPUs.
Posted
by fzhinkin.
Last updated
.
Post not yet marked as solved
1 Replies
774 Views
If I create a new project with the following code in main.swift and then Profile it in Instruments with the CPU Profiler template, nothing is logged in the Points of Interest category. I'm not sure if this is related to the recent macOS 14.2 update, but I'm running Xcode 15.1. import Foundation import OSLog let signposter = OSSignposter(subsystem: "hofstee.test", category: .pointsOfInterest) // os_signpost event #1 signposter.emitEvent("foo") // os_signpost event #2 signposter.withIntervalSignpost("bar") { print("Hello, World!") } If I change the template to the System Trace template and profile again, then the two os_signpost events show up as expected. This used to work before, and this is a completely clean Xcode project created from the macOS Command Line Tool template. I'm not sure what's going on and searching for answers hasn't been fruitful. Changing the Bundle ID doesn't have any effect either.
Posted
by hofstee.
Last updated
.
Post not yet marked as solved
1 Replies
505 Views
What's the best way in Instruments, to measure the amount of time spent on large memory copies? For a very simple example, when directly calling memcpy? Memory copying does not show up in the time profiler, it's not a VM cache miss or zeroing event, etc so it doesn't show there, it doesn't (as far as I can tell) show up in the system trace, and there aren't any other choices.
Posted
by swillits.
Last updated
.
Post marked as solved
5 Replies
1k Views
Has anyone else created a macOS SwiftUI app that uses a Table with a largish (~1000) number of entries? My app works OK at about 100 entries, but slows down as the number of entries increase. How slow? An instrumented test with 1219 entries shows a Hang of over 13 seconds from simply clicking/selecting an item in the table. Instruments says the time is mostly spent in _CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION. Digging deeper I see AG::Subgraph::update(unsigned int) and descendants account for about half of the hang time. My app is using @Observable on macOS 14 and is being tested on an M2 Max Studio. There are other reported hangs. All seem to be in Swift/SwiftUI code.
Posted
by marchyman.
Last updated
.
Post not yet marked as solved
3 Replies
558 Views
Xcode Version 15.2 (15C500b) After upgrading Xcode from 14 to 15.2 I am not able to attach system extension (packettunnel) process to Instruments tools for memory debugging. Same is working fine with Xcode 14. Error displayed: "Process No Longer Exists". But the service is running and is listed in process list. % ps -ax | grep -i pkttunnel | grep -v grep 61910 ?? 0:01.04 /Library/SystemExtensions/5F4AF6EF-****-****-****-F11****9CE78/com.******.client.*****-Client.***ui.***pkttunnel.systemextension/Contents/MacOS/com.******.client.*****-Client.***ui.***pkttunnel.systemextension Note: I am able to attach a normal program to Instruments tool for memory debugging, I have noticed this issue with system extension processes only.
Posted
by macnd.
Last updated
.
Post not yet marked as solved
2 Replies
554 Views
If I try to run Instrument's logger for an app downloaded from TestFlight it says "Permission to debug app name was denied". "Recover Suggestion: The app must be debuggable and signed with 'get-task-allow'. How do you make the app debuggable? (I tried creating an archive with the scheme set to Debug, but after uploading that to TestFlight, it doesn't appear. So presumably its not possible to upload an app built with debug scheme builds to TF?). Therefore how can I make a TF build debuggable?, and how to sign it with get-task-allow? Does it have to be a developer distribution .ipa rather than a TestFlight build to enable Instruments/Logger to run it?
Posted
by mungbeans.
Last updated
.
Post not yet marked as solved
12 Replies
652 Views
I asked a similar question last year, and got no responses. I've written a much simpler (no network extension!) case that seems to demonstrate what I'm confused about. Simple app with an XPC service. I have an ObjectiveC class TestObject which has an NSString* and an NSData* (which I never actually use). I have a protocol defined in Swift: @objc protocol XPCTestServiceProtocol { func logData(entry: TestObject) -> Void func logData(entry: TestObject, completion: ((String) -> Void)) } In the Switt XPC service, the code is: class XPCTestService: NSObject, XPCTestServiceProtocol { var totalBytes = 0 var lastName = "" @objc func logData(entry: TestObject) { totalBytes += (entry.data?.count ?? 0) } @objc func logData(entry: TestObject, completion: ((String) -> Void)) { totalBytes += (entry.data?.count ?? 0) completion("Finished") } I've got this code in the ObjC app: id<XPCTestServiceProtocol> proxy = [self.connection remoteObjectProxyWithErrorHandler:^(NSError* error) { self.stopRun = YES; NSLog(@"Proxy got error %@", error); }]; while (self.stopRun == NO) { @synchronized (self) { NSNumber *objNum = [NSNumber numberWithUnsignedLongLong:self.count++]; NSString *objName = [NSString stringWithFormat:@"Object %@", objNum]; TestObject __weak *toWeak = to; #if USE_COMPLETION [proxy logDataWithEntry:to completion:^(NSString *str) { to = nil; }]; #else [proxy logDataWithEntry:to]; #endif } } attached to a start button (and self.stopRun is set by a stop button, this is all super simple). So I run that, start the test, and things start going (122k calls/second it says). According to Activity Monitor, my app is using about 1gbyte after 20 seconds or so. However, if I run it under Instruments' Leaks template... Activity Monitor says it's used only about 60mbytes. (And at the end of the run, Instruments says it's used about 30mbytes.) Now... if I use the completion and a synchronous proxy, then even without Instruments, Activity Monitor says it's 60mbytes or so. Is the memory reported by Activity Monitor real? Or not real?
Posted
by kithrup.
Last updated
.
Post not yet marked as solved
0 Replies
523 Views
Hi everyone, I have an AR app that allows for collaborative sessions and synchronizes model state (e.g. rotation, can be changed via slider) using Multipeer Connectivity. The receiving peer parses the data and then uses DispatchQueue.main.async to update the UI (SwiftUI) and the model in SceneKit. Lately I have noticed that this synchronization seems to lag periodically. To analyze the issue better I compiled this minimal reproducible example: https://github.com/MrMuetze/MCSyncTest The repository includes a boiled down "Multipeer Connectivity" project that should make this issue reproducible on local devices (maybe even between one device and the simulator). I have also added a readme with a gif that shows the issue. The synchronization between devices worked like a treat for a long time but recently I have noticed that e.g. a rotation is not as smooth as before on the receiving device. A bit of debugging revealed that the messages are received quickly but then the work that needs to happen on the main thread is periodically delayed. In the example project the relevant code bit that should be executed on the main thread looks like this: func session(_: MCSession, didReceive data: Data, fromPeer _: MCPeerID) { print("received data") DispatchQueue.main.async { print("doing stuff") let doubleVal = data.to(type: Double.self) ?? 0.0 self.internalSliderValue = doubleVal self.sliderValue = doubleVal } } It updates a published variable sliderValue that is connected to a Slider and a Text UI element. Regularly (like every 500ms or so) the execution of work on the main thread seems to be delayed. After a short while all outstanding UI updates are executed at once which leads to visual stuttering. This can be observed by looking at the printed messages: ... received data &lt;-- normal behavior doing stuff received data doing stuff received data doing stuff received data &lt;-- hiccup starts received data received data received data doing stuff doing stuff doing stuff doing stuff received data &lt;-- returns to normal behavior doing stuff received data doing stuff ... I have tried to change the "Quality of Service" to .userInteractive as well as limiting the number of messages that are sent in a certain timeframe (I tried one message every 100ms). Both changes have not helped and even with a much lower number of messages the periodic stuttering remains. Using DispatchQueue.main.sync is also not a solution right now. It does bring the sequence back into original order but the periodic "freeze" of the queue is prevalent there as well. This then leads to a "laggy" execution of what happened on the sending peer device. I am not very familiar with Profiling an app and using Instruments, but I have captured some timings in regards to the usage of the main thread and some backtraces. From what I can understand the workload of the written code should not be the issue, but rather an underlying system function or library. I can provide more information in regards to the backtraces if needed. Right now I can't really say what would be useful. Below is an image that shows the main thread usage at the very top. This happens when the slider lags as shown in the gif. I am working with Xcode 15.2 and run the app on iOS 17.3. For devices I use an iPad Pro (2nd gen.) and an iPhone 15 Pro. The issue happens in Debug as well as in Release mode. I can't quite say when the stuttering appeared initially. I wonder if anyone is aware of any changes to iOS or underlying frameworks that could have caused this issue. I am interested in any information about this, if the issue can be resolved or if I have to look for alternative workarounds. Let me know if I can add any additional information. Best regards! Bjoern
Posted
by MrMuetze.
Last updated
.
Post not yet marked as solved
2 Replies
456 Views
Hi! I watched the 'Analyze hangs with Instruments' video from WWDC2023. It's such a great video! Unfortunately, I found a case that the video doesn't cover when profiling my browser app using Instruments: As shown in the image, the hangs still occur even though my main thread is not busy, and I've also used the 'Thread State Trace instrument' to confirm that the main thread is not blocked either. I'm not sure what the next step is to resolve the hangs. Any insight or guidance would be much appreciated. Thank you!"
Posted Last updated
.
Post not yet marked as solved
1 Replies
346 Views
Context I'm trying to profile a binary (a simple C++ program compiled into dummy.o) and collect CPU Counters data. I have a configuration that works fine from the Instruments Counters GUI (see Screenshots below). I've exported this configuration to a template file named prof1.tracetemplate. Problem When I try to run a recording with that same template from the command line with xctrace (I also tried with sudo): $ xctrace record --template prof1.tracetemplate --launch dummy.o I get the following errors: Starting recording with the prof1 template. Launching process: dummy.o. Ctrl-C to stop the recording Run issues were detected (trace is still ready to be viewed): [Error] Unexpected failure: Couriers have returned unexpectedly. [Error] Failed to start the recording: Failed to force all hardware CPU counters: 13. [Error] Failed to pause recording session: Cannot pause session session unless it's running. Current state: kSessionError [Error] Unexpected failure: Data source agent failed to arm. Recording failed with errors. Saving output file... Output file saved as: Launch_dummy.o_2024-01-31_14.22.32_0B6E1A78.trace System Chip: Apple M1 macOS: 14.1.1 (23B81) xctrace version: 15.2 (15C500b) xcode version: 15.2 (15C500b) Screenshots
Posted Last updated
.