I'm trying to profile app startup after moving from static libraries to frameworks. We have 30 or so frameworks (fyi: cocoapods) so I want to check that it's not affecting performance. Anecdotal testing in the team says that it isn't, but I would like some numbers as well!
I've added the environment variables DYLD_PRINT_STATISTICS and DYLD_PRINT_LIBRARIES to see what the linker is doing, but all the output I get is from the DYLD_PRINT_LIBRARIES variable. I can see that the frameworks are loading correctly, but get no statistics from them.
I've tried restarting the device to make sure that the frameworks aren't in memory already but that hasn't helped.
Any other suggestions as to why I'm not getting any output from DYLD_PRINT_STATISTICS?
Looks like you can do it on device if you enable both environment variables in your scheme:
DYLD_PRINT_APIS = YES
DYLD_PRINT_STATISTICS = YES
Reference:
https://github.com/artsy/eigen/issues/586#issuecomment-118606377
While other flags, like DYLD_PRINT_BINDINGS work fine on the device, DYLD_PRINT_STATISTICS only seems to work on the simulator (for me, iOS 9.0).
In this (possibly unrelated) version of dyld.cpp, from osx 10.10.5 there doesn't seem to be any obvious exclusion of DYLD_PRINT_STATISTICS for devices, although there are conditionally compiled TARGET_IPHONE_SIMULATORs sprinkled throughout the code.
I guess it's a bug.
Related
I have an application written in Swift on SceneKit + Metal. When I build and run the app from Xcode fps counter shows 40fps. But if I run the app myself by tapping the icon on springboard fps counter shows 60fps. How could it be? Could Xcode somehow affect app performance while debugging? I have no idea how this all works, but I suppose there could be some hooks for debugging to work correctly which affect performance. If so, can I opt-in from this?
I'm aware of different build flags for debug and release builds, but I don't make release build. Performance differs in the same debug build while running from Xcode vs when I run the app manually on the phone.
By default, Xcode enables the Metal validation layer. That does a bunch of additional checking of how you're using it to catch incorrect uses. The additional checking is slow, which is why Metal doesn't do it unless validation is enabled.
This can be changed in Xcode's Scheme editor. This is documented in Apple's Metal Programming Guide.
A nice tutorial on iOS Assembly. This might be insightful on the topic
As stated, this is because the compiler is in debug mode, meaning no optimizations are made. If you turn optimizations on, then you’ll see a much smaller function generated.
And also check out this answer about changing optimization levels.
I've experimented with different options in scheme editor and have find out that Debug executable checkbox affected performance in my case. So my assumption about debugger was right, but I didn't know about that checkbox before.
I have a iOS Swift app. I recently added a feature and uploaded the new version to TestFlight. For some reason, the main function for this new feature is not being called in release mode, but works perfectly in debug mode.
What I tried so far: within 'Apple LLVM 6.0 - Code Generation' for Release
1) Changed Optimization Level to None, and
2) Changed 'Symbols Hidden By Default' to No
I do not believe that the function's specifics matter here, but for what it's worth: it receives and manipulates some JSON data from the backend. I have ten other functions which do exactly the same thing for different types of data - not facing the same problem there.
Any ideas around this? What other differences are there between Release Mode and Debug Mode? that might be a good start to troubleshoot.
Thanks,
What other differences are there between Release Mode and Debug Mode?
Aside from different device architectures, there's a DEBUG preprocessor macro that is excluded in Release.
You can make a scheme that allows you to debug in Release mode, and check where it breaks.
Assertions will not run in release mode. Sometimes people make this mistake (I've made it a few times over the years):
assert(doSomethingImportant(), "Failed")
This works in Debug, but doSomethingImportant doesn't get called in Release.
I'm trying to use Time Profiler, I've used it before.
I'm hiding system libraries, but all of my symbol names are HEX.
I'm running in debug, I have debugSymbols turned on....
I've restarted everything a few times and cleaned everything in between..
... anybody got any other ideas?
it's a bit of a pain because there are a number of variables that can cause this. some of the more common ones are:
sometimes you need to tell instruments where to find your files and/or symbols (Preferences->Search Paths).
have you enabled Link Time Optimization (LTO)? it should be off.
sometimes it helps if you do a clean/build.
sometimes it helps if you restart instruments.
in earlier versions of Xcode, it helped to use a central build directory.
verify that you are generating the proper level of debug symbols for all targets.
I no longer get this problem with the latest version.
Apple were no help in answering this for me - even though I used one of my Tech Support Requests. Must have had them stumped too.
I have a bit of a dilemma — no matter what I do, I cannot get Apple's Instruments.app to symbolicate any of the included instruments while I'm profiling on my devices (it works OK in the iOS Simulator).
I've tried just about everything I can think of, including:
Checking that I'm actually building a dSYM
Switching between Debug and Release build schemes
Making sure that the signing certificate being used in my Development cert
Adding and removing my Derived Data folder from Spotlight's Privacy list
Clean & Build before profiling
Removing the Derived Data folder before building and profiling
I'm not sure where to go from here — I had symbols for an hour or two earlier in the week, but I just can't get them to show up at all anymore. It would be great to figure out what the mystical incantation is to make Instruments always find my app's symbols.
In the File menu there is an option for Re-Symbolicate Document. Choosing this, you can find your binary in the list and use the Locate button to specify the location of the dSYM manually. There is also a checkbox here for using Spotlight to find the dSYM; it's possible it got deactivated if Spotlight was borked at some point but is now fixed.
It seems that you cannot do this while Instruments is actually instrumenting, but it does seem to keep the setting for the next time you hit Record. It does not, however, seem to remember the setting after you close Instruments.
Did you ensure you are signing the app with a development profile (as opposed to a distribution profile)?
Be aware that you are usually using release builds with instruments so make sure you didn't choose a distribution profile for your release configuration...
I've seen Instruments 4.2 fail to symbolicate several times with the correct dSYM file.
After saving and quit/restart Instruments, it will then symbolicate.
(Sometimes I'll capture a small sample and make sure it works before collecting large samples.)
Aside from xcode's tools, you can use atos: https://stackoverflow.com/a/4954949/312725
Be sure to take slide into account as well: https://stackoverflow.com/a/13576028/312725
(I'm adding this information to several related questions that are related to that, but aren't exactly duplicate questions. This is copy-pasted, it's a honest attempt to help someone who googled that question rather then spam.)
I've developed and application for iPhone. It works fine on os4 but it does not work on os3.1. In fact works but there are some problems; after splash screen a what screen appears. while I leaving the application I can see the application is opened successfully but just see while exiting.
So I wonder if there is a tool which says which apis have problems with os3.1? So I have a chance to replace them.
If you want to check a specific API, just run this in your code somewhere with an appropriate response. For example, to see if print is supported, run this...
if (NSClassFromString(#"UIPrintInfo")) {
}
Set your project's Base SDK to iphone-os-3-1, then build. All the error messages about classes, methods, and functions that don't exist must designate things added since iphone-os-3-1, since your project built and linked fine against the iphone-os-4-0 SDK.
If you don't have the iphone-os-3-1 SDK, try this instead:
Open your project's Build Settings.
Find the "Preprocessor Macros" setting.
Edit it and add __IPHONE_OS_VERSION_MAX_ALLOWED=30100
Now, try building. This should cause everything introduced after iOS 3.1 to be labeled unavailable, producing the same errors as if you had switched to the iphone-os-3-1 SDK.
It's a good idea to get a second installation of Xcode for this situation, in this case you need 3.2.1 with SDK 3.1.3 - I wish I could help you with a download link since it is no longer shown on Apple's page, but I have googled in the past and found direct, official download links which will work as long as you are signed in with your developer account, so good luck.
The annoying bit is that you need to go through your project files and set "Base SDK" to 3.1.3 and then back once you have completed the exercise. But it is the easiest way to flag what you can't do in 3.1.3. "sudo rm -rf" (I feel nervous even typing that) has an excellent method there but you need to have an inkling of what might be safe and what might not before you implement it or else you end up with code 10x the size it needs to be.
Apple really needs to sort out this issue - hopefully by flagging methods that are prior to your specified "Deployment Target", in the same way that deprecated methods are flagged.