Will NSLog effect app's speed? [duplicate] - iphone

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Do I need to disable NSLog before release Application?
In my iPhone app there are more than 20 classes.Every where I am printing so many values using NSLog.When I run my app on simulator it is bit low because of some NSLogs(specially printing NSData etc)
Will it be slow if I finished the app and run it on device after making the ipa file ?
Or should I comment all the NSLogs from classes ?

yes it does. and if u wanna check it by urself, do profiling with allocations, and see what is taking much of your memory. It will show NSLogs also.

instead of NSLog use DLog everywhere. When testing and debugging, you'll get debug messages. When you're ready to release a beta or final release, all those DLog lines automatically become empty and nothing gets emitted. This way there's no manual setting of variables or commenting of NSLogs required. Picking your build target takes care of it.

NSLog will affect speed as it blocks and causes IO. It runs synchronously in the current thread.
better is something async! -- like cocoalumberjack's DDLog which is a drop in replacement that doesnt block. [still can cause IO, see next info about levels]
ALSO DDLog knows about log levels. E.G. info, Warning & Error:
in release mode you set it to error by default (but it can be changed via a UserDefault value!)
warnings and infos are not logged then which makes it cause only VERY little overhead
DDLog is similar to log4j but for objC!

Related

VSCode exits while debugging a flutter app

It seems like vscode is trying to present data in the Locals and/or Watch for a large object but after about 10 seconds, it will kill the app and give the message "Exited (sigterm)" in the debug console. I can pinpoint it to one example where I break on a line immediately after this line:
Uint8List inputBytes = Uint8List.fromList(List.filled(100000000, 0));
I can see "Locals" spinning around but nothing happens and then the app terminates. Is there a setting that can prevent this somehow? Maybe it can cap the represented data at a certain length instead of trying to print it all out?
(I believe this is a vscode specific problem because when I repeat these steps in Android Studio, it doesn't have this issue)
Thanks.
This is a bug in the debug adapter. It should know this is a list and fetch a paged view of the elements, but it's currently fetching them all. For me it doesn't crash, but it also doesn't respond within several minutes.
I'm working on a fix that will let VS Code page through the data:
This will ship in an upcoming Dart/Flutter SDK release.

Confusing error from libasound function snd_pcm_hw_params

My question has to do with the libasound function named "snd_pcm_hw_params" in connection with code to play a sound file. I am new to ALSA programming. Using a coding example I found on the internet, I wrote a small program to play a 7 second .wav file to the default sound card. When I run this code several times in a row, occasionally (but not always) the requisite call to snd_pcm_hw_params to write the previously filled in snd_hw_params_t struct to the driver, I get back an error code of -2 (ENOENT). I have no idea what this means, nor how to handle nor prevent it. My code just emits an error message and bails. Usually, if I run it again, the code runs fine. Its fine for my use, but eventually, this code is supposed to be given to a non-programmer to use, and I'd like to either prevent the error, or resolve it internally without involving said non-programming user. I note hear that the user is supposed to be able to cause an early abort of the program by clicking a button, and when this happens, my code calls snd_pcm_drop, followed by snd_pcm_close. If the program runs to completion, and plays all 7 seconds of the wav file, then it finishes up by calling snd_pcm_drain, followed by snd_pcm_close. Any help or suggestions would be greatly appreciated. :)

XCode debugger not helping find device-only issue

So, I have an iOS tabbed app (live and free in the store [http://itunes.com/apps/iphoundyou]). One tab is a grouped tableview, with the number of groups (1 or 2) dependent on some JSON that a web service returns. The JSON is valid and straightforward. Handling it seems to be easy, and, when run in the simulator, behaves as expected. However, I just found that when run on the device, if the two section reaction is needed...it crashes.
"ok" I thought "I'll just hook up my device, launch the debugger, replicate the crash, and figure out where I have a bug"
However, when I did that, I get the most unhelpful response I could expect:
So, given that it works in the simulator, is there any suggestions as to how else to track down the flaw? The code for the tableview is nothing special, along the lines of "if this JSON key exists, number of sections=2...with the number of rows of that section equal to the number of items in another array within the JSON"
Another note: I recently started seeing a dozen or so of these when launching an app:
unable to read unknown load command 0x25
unable to read unknown load command 0x26
Thanks so much.
In my case it turned out that it was just my own error: I'd updated my device OS but didn't have that SDK (I was behind in updating XCode)

What causes “EXC_BAD_ACCESS” error when getting wifi information?

I'm getting the following error
Program received signal: “EXC_BAD_ACCESS”.
warning: check_safe_call: could not restore current frame
warning: Unable to restore previously selected frame.
warning: Unable to restore previously selected frame.
My app is to get wifi information
libHandle = dlopen("/System/Library/PrivateFrameworks/ MobileWiFi.framework/MobileWiFi",RTLD_LAZY);
open = dlsym(libHandle, "Apple80211Open");
bind = dlsym(libHandle, "Apple80211BindToInterface");
close = dlsym(libHandle, "Apple80211Close");
scan = dlsym(libHandle, "Apple80211Scan");
open(&airportHandle);
bind(airportHandle, #"en0");
When the code reaches open(&airportHandle), I receive the error but I'm not sure because at this line it stops.
How can I resolve this?
For any EXC_BAD_ACCESS errors, you are usually trying to send a message to a released object. The BEST way to track these down is use NSZombieEnabled.
This works by never actually releasing an object, but by wrapping it up as a "zombie" and setting a flag inside it that says it normally would have been released. This way, if you try to access it again, it still know what it was before you made the error, and with this little bit of information, you can usually backtrack to see what the issue was.
It especially helps in background threads when the Debugger sometimes craps out on any useful information.
VERY IMPORTANT TO NOTE however, is that you need to 100% make sure this is only in your debug code and not your distribution code. Because nothing is ever released, your app will leak and leak and leak. To remind me to do this, I put this log in my appdelegate:
if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled"))
NSLog(#"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");
If you need help finding the exact line, Do a Build-and-Debug (CMD-Y) instead of a Build-and-Run (CMD-R). When the app crashes, the debugger will show you exactly which line and in combination with NSZombieEnabled, you should be able to find out exactly why.
EXC_BAD_ACCESS always occurs when accessing memory you already have released. In your sample code, I can't see where airportHandle is initialized, or wheter it is initialized at all for that matter.
If it has been initialized but you just forgot to post that code, you should try checking if you released the handle somewhere.
To debug such an access violation, it is often useful to set the NSZombieEnabled Environment flag to YES. This will cause the Obj-C runtime to log access to released memory to the console. You can find a full tutorial on how to use that information together with Instruments to find your problem.
You can do it EASILY with Instruments: See this really great post:
http://www.corbinstreehouse.com/blog/2007/10/instruments-on-leopard-how-to-debug-those-random-crashes-in-your-cocoa-app/comment-page-1/#comment-43762
EXC_BAD_ACCESS. is mainly found when u released any object which you have further needed in future.it is unable to find but there is solution to find out u must have to be in a DEBUG mode . then follow these links
http://www.codza.com/how-to-debug-exc_bad_access-on-iphone
it really works
I'm working on the same thing, and I get the same issue. If you enter in debug mode, you can see that when we use open = dlsym(libHandle, "Apple80211Open"); the function still equals to 0.
So in my opinion you are looking for the Apple80211Open in a framework which did not contain this function.
Apple80211Open is in the Apple80211 private framework which is outdated in >iOS 2.x SDK. The equivalent in the MobileWifi framework, which is for the 3.x and 4.x SDK, is /System/Library/SystemConfiguration/WiFiManager.bundle/WiFiManager instead of /System/Library/PrivateFrameworks/MobileWiFi.framework/MobileWiFi

Is it true that one should not use NSLog() on production code?

I was told this a few times in this very site, but I wanted to make sure this is really the case.
I was expecting to be able to sprinkle NSLog function calls throughout my code, and that Xcode/gcc would automatically strip those calls out when building my Release/Distribution builds.
Should I avoid using this? If so, what alternatives are most common between experienced Objective-C programmers?
Preprocessor macros are indeed great for debugging. There's nothing wrong with NSLog(), but it's simple to define your own logging function with better functionality. Here's the one I use, it includes the file name and line number to make it easier to track down log statements.
#define DEBUG_MODE
#ifdef DEBUG_MODE
#define DebugLog( s, ... ) NSLog( #"<%p %#:(%d)> %#", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define DebugLog( s, ... )
#endif
I found it easier to put this entire statement in the prefix header rather than its own file. You could, if you wanted, build a more complicated logging system by having DebugLog interact with normal Objective-C objects. For instance, you could have a logging class that writes to its own log file (or database), and includes a 'priority' argument you could set at runtime, so debug messages are not shown in your release version, but error messages are (if you did this you could make DebugLog(), WarningLog(), and so on).
Oh, and keep in mind #define DEBUG_MODE can be re-used in different places in your application. For example, in my application I use it to disable license key checks and only allow the application to run if it's before a certain date. This lets me distribute a time limited, fully functional beta copy with minimal effort on my part.
Put this 3 lines at the end of -prefix.pch file:
#ifndef DEBUG
#define NSLog(...) /* suppress NSLog when in release mode */
#endif
You don't need to define anything into your project, because DEBUG is defined in your build setting by default when you create your project.
NSLog calls can be left in production code, but should only be there for truly exceptional cases, or information that it is desired that will be logged to the system log.
Applications which litter the system log are annoying, and come across as unprofessional.
I can't comment on Marc Charbonneau's answer, so I'll post this as an answer.
Further to adding the macro to your pre-compiled header, you can use the Target build configurations to control the defining (or lack of defining) the DEBUG_MODE.
If you select "Debug" active configuration, DEBUG_MODE will be defined, and the macro expands to the full NSLog definition.
Selecting the "Release" active configuration will not define DEBUG_MODE and your NSLogging is omitted from the release build.
Steps:
Target > Get Info
Build tab
Search for "PreProcessor Macros" (or GCC_PREPROCESSOR_DEFINITIONS)
Select Configuration: Debug
Edit Definition at this Level
Add DEBUG_MODE=1
Select Configuration: Release
confirm DEBUG_MODE is not set in GCC_PREPROCESSOR_DEFINITIONS
if you omit the '=' character in the definition, you will get an error from the preprocessor
Also, paste this comment (shown below) above the macro definition to remind you where the DEBUG_MACRO define comes from ;)
// Target > Get Info > Build > GCC_PREPROCESSOR_DEFINITIONS
// Configuration = Release: <empty>
// = Debug: DEBUG_MODE=1
EDIT: The method posted by Marc Charbonneau, and brought to my attention by sho, is far better than this one.
I have deleted the portion of my answer which suggested using an empty function to disable logging when debug mode is disabled. The portion that deals with setting an automatic preprocessor macro is still relevant, so it remains. I have also edited the name of the preprocessor macro so that it fits better with Marc Charbonneau's answer.
To achieve the automatic (and expected) behaviour in Xcode:
In the project settings, go to the "Build" tab, and select the "Debug" configuration. Find the "Preprocessor Macros" section, and add a macro named DEBUG_MODE.
...
EDIT: See Marc Charbonneau's answer for the proper way to enable and disable logging with the DEBUG_MODE macro.
I agree with Matthew. There's nothing wrong with NSLog in production code. In fact, it can be useful to the user. That said, if the only reason you're using NSLog is to help debug, then, yes, that should be removed before you release.
Furthermore, since you've tagged this as an iPhone question, NSLog takes resources, which is something the iPhone has precious little of. If you're NSLogging anything on the iPhone, that takes away processor time from your app. Use it wisely.
The simple truth is that NSLog is just plain slow.
But why? To answer that question, let's find out what NSLog does, and then how it does it.
What does NSLog do exactly?
NSLog does 2 things:
It writes log messages to the Apple System Logging (asl) facility. This allows log messages to show up in Console.app.
It also checks to see if the application's stderr stream is going to a terminal (such as when the application is being run via Xcode). If so it writes the log message to stderr (so that it shows up in the Xcode console).
Writing to STDERR doesn't sound difficult. That can be accomplished with fprintf and the stderr file descriptor reference. But what about asl?
The best documentation I've found about ASL is a 10 part blog post from Peter Hosey: link
Without going into too much detail, the highlight (as it concerns performance) is this:
To send a log message to the ASL facility, you basically open a client connection to the ASL daemon and send the message. BUT - each thread must use a separate client connection. So, to be thread safe, every time NSLog is called it opens a new asl client connection, sends the message, and then closes the connection.
Resources could be found here & here.
As noted in other answers you can use a #define to alter whether NSLog is used or not at compile time.
However a more flexible way is to use a logging library like Cocoa Lumberjack thatallows you to change whether something is logged at runtime as well.
In your code replace NSLog by DDLogVerbose or DDLogError etc, add a #import for the macro definitions etc and setup the loggers, often in the applicationDidFinishLaunching method.
To have the same effect as NSLog the configuration code is
[DDLog addLogger:[DDASLLogger sharedInstance]];
[DDLog addLogger:[DDTTYLogger sharedInstance]];
From a security point of view, it depends on what is being logged. If NSLog (or other loggers) is writing sensitive information, then you should remove the logger in production code.
From an auditing point of view, the auditor does not want to look at each use of NSLog to ensure its not logging sensitive information. He/she will simply tell you to remove the logger.
I work with both groups. We audit code, write the coding guides, etc. Our guide requires that logging is disabled in production code. So the internal teams know not to try it ;)
We will also reject an external app that logs in production because we don't want to accept the risk associated with accidentally leaking sensitive information. We don't care what the developer tells us. Its simply not worth our time to investigate.
And remember, we define 'sensitive', and not the developer ;)
I also perceive an app which performs lots of logging as an app ready to implode. There's a reason so much logging is performed/needed, and its usually not stability. Its right up there with 'watchdog' threads that restart hung services.
If you have never been through a Security Architecture (SecArch) review, these are the sorts of things we look at.
You shouldn't be needlessly verbose with printf or NSLog in release code. Try only doing a printf or NSLog if the app has something bad happen to it, I.E. an unrecoverable error.
Keep in mind that NSLogs can slow down the UI / main thread. It is best to remove them from release builds unless absolutely necessary.
I would highly recommend using TestFlight for logging (free). Their method will override NSLog (using a macro) and allow you to turn on/off logging to their server, Apple System log and STDERR log, for all your existing calls to NSLog. The nice thing about this is you can still review your log messages for apps deployed to testers and apps deployed in the App Store, without the logs appearing on the user's system log. The best of both worlds.