Is there a cost to using NSLog liberally? - iphone

As a newer programmer, I've discovered the magic of NSlog, and use it all through my code. It's been extremely helpful (along with NSZombieEnabled) in debugging.
I can see a definite performance hit on the simulator as it prints out all this stuff. I don't think I see any such hit on devices, but I'm not sure.
So does it cost anything to leave all the NSLogs in? Is it using more memory on the device? Or does the compiler just ignore them, like it does comments when I compile for a device?
EDIT:
Here's what I implemented, per the suggestion from rano.
In my App_Prefix.pch file, I added:
// DLog is almost a drop-in replacement for NSLog
// DLog();
// DLog(#"here");
// DLog(#"value: %d", x);
// Unfortunately this doesn't work DLog(aStringVariable); you have to do this instead DLog(#"%#", aStringVariable);
#ifdef DEBUG
# define DLog(fmt, ...) NSLog((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
# define DLog(...)
#endif
// ALog always displays output regardless of the DEBUG setting
#define ALog(fmt, ...) NSLog((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
And then in my Project Info inspector, for the Debug configuration, under the heading GCC 4.2 - Preprocessing, I added the value DEBUG to the top entry called, Preprocessor Macros.
Works like a charm - DLog outputs when I build a Debug version and ALog always outputs.

NSLog surely is more pricy than a simple printf but is a little more integrated into the objective-C and Cocoa framework.
By the way when you are seriously programming you will notice that it is unsufficient to most of your needs. Take a look at this article and its references to have an idea on how to replace it in a smart way.
In that way you can also have the compiler to ignore it when it is no more useful (e.g. when you will release your piece of code). In general you could #ifdef the calling to a log function in computing intensive loops/sequences of code.

NSLog is not implemented as a macro, so there will definitely be a cost. Quantifying it and deciding if it is important is harder. The only sure way to do that is to measure your own application.

The answers above are outdated. You should simply use CocoaLumberjack is vastly superior to NSLog and provides much more functionality then the above answers.

Related

Swift equivalent of forcing a build failure based on certain macro definitions

In Objective-C, you can trigger a build error based on macros. For example, say I have this macro defined:
#define DEBUG_ALL_LOGS
Then in my logging framework:
-(void)logMessage:(NSString *)message severity:(int)severity
{
#ifdef DEBUG_ALL_LOGS
NSLog(#"Log message level %i: '%#'", severity, message);
#endif
//Now pass the log message off to a file or whatever
}
To prevent this from making it into a production build, I can have something like this:
#if defined(DEBUG) && defined(DEBUG_ALL_LOGS)
#error Forcing all logs is only allowed in debug builds
#endif
(side note: this exact setup might not do what you expect because of DEBUG vs NDEBUG, but this is pseudocode-ish)
Now I can turn debug behavior on and off without worrying (much) about it making it into a production build.
How can I accomplish this in Swift? Swift doesn't have macros, and uses global constants instead. But I don't think I can cause a compile error based on the value of a variable.

Can I trigger a breakpoint on OpenGL errors in Xcode 4?

Is there any way I can set a symbolic breakpoint that will trigger when any OpenGL function call sets any state other than GL_NO_ERROR? Initial evidence suggests opengl_error_break is intended to to serve just that purpose, but it doesn't break.
Based on Lars' approach you can achieve this tracking of errors automatically, it is based on some preprocessor magic and generating stub functions.
I wrote a small Python script which processes the OpenGL header (I used the Mac OS X one in the example, but it should also work with the one of iOS).
The Python script generates two files, a header to include in your project everywhere where you call OpenGL like this (you can name the header however you want):
#include "gl_debug_overwrites.h"
The header contains macros and function declarations after this scheme:
#define glGenLists _gl_debug_error_glGenLists
GLuint _gl_debug_error_glGenLists(GLsizei range);
The script also produces a source file in the same stream which you should save separately, compile and link with your project.
This will then wrap all gl* functions in another function which is prefixed with _gl_debug_error_ which then checks for errors similar to this:
GLuint _gl_debug_error_glGenLists(GLsizei range) {
GLuint var = glGenLists(range);
CHECK_GL_ERROR();
return var;
}
Wrap your OpenGL calls to call glGetError after every call in debug mode. Within the wrapper method create a conditional breakpoint and check if the return value of glGetError is something different than GL_NO_ERROR.
Details:
Add this macro to your project (from OolongEngine project):
#define CHECK_GL_ERROR() ({ GLenum __error = glGetError(); if(__error) printf("OpenGL error 0x%04X in %s\n", __error, __FUNCTION__); (__error ? NO : YES); })
Search for all your OpenGL calls manually or with an appropriate RegEx. Then you have two options exemplary shown for the glViewport() call:
Replace the call with glViewport(...); CHECK_GL_ERROR()
Replace the call with glDebugViewport(...); and implement glDebugViewport as shown in (1).
I think that what could get you out of the problem is to capture OpenGL ES Frames (scroll down to "Capture OpenGL ES Frames"), which is now supported by Xcode. At least this is how I am debugging my OpenGL Games.
By capturing the frames when you know an error is happening you could identify the issue in the OpenGL Stack without too much effort.
Hope it helps!

How to log all methods used in iOS app

I'm taking over the development of an iPad app for a client. There's a substantial amount of work that's already been done and I'm trying to piece together how the whole thing is designed to run.
One of the things I'd like to do is log which methods get called when the app runs. I've seen a custom DTrace script that's meant to log all methods from startup, but when I run it in Instruments I get no results.
What's the best way of logging the methods?
Inspired by tc's answer to a similar question here, I put together a debug breakpoint action that will log out the class and method name for every time objc_msgSend() is triggered in your application. This works similarly to the DTrace script I described in this answer.
To enable this breakpoint action, create a new symbolic breakpoint (in Xcode 4, go to the breakpoint navigator and create a new symbolic breakpoint using the plus at the bottom left of the window). Have the symbol be objc_msgSend, set it to automatically continue after evaluating actions, and set the action to be a debugger command using the following:
printf "[%s %s]\n", (char *)object_getClassName(*(long*)($esp+4)),*(long *)($esp+8)
Your breakpoint should look something like the following:
This should log out messages like this when run against your application:
[UIApplication sharedApplication]
[UIApplication _isClassic]
[NSCFString getCString:maxLength:encoding:]
[UIApplication class]
[SLSMoleculeAppDelegate isSubclassOfClass:]
[SLSMoleculeAppDelegate initialize]
If you're wondering where I pulled the memory addresses, read this Phrack article on the Objective-C runtime internals. The memory addresses above will only work against the Simulator, so you might need to tweak this to run against applications on the iOS devices. Collin suggests the following modification in his answer to run this on a device:
printf "[%s %s]\n", (char *)object_getClassName($r0),$r1
Also, I think you'll see that logging out every method called in your application will overwhelm you with information. You might be able to use some conditions to filter this, but I don't know if this will help you to learn how your code executes.
If you are using LLDB, you will need to use the following debugger commands. These were tested in Xcode 4.6.
Device:
expr -- (void) printf("[%s %s]\n", (char *)object_getClassName($r0),$r1)
Simulator:
expr -- (void) printf("[%s %s]\n", (char *)object_getClassName(*(long*)($esp+4)), *(long *)($esp+8))
To trace the app code under Xcode 6 on device, I had to use the following debugger expression.
expr -- (void) printf("[%s %s]\n", (char *)object_getClassName($arg1),$arg2)
Brad Larson's approach can be adapted to run on the device by using the debugger command:
printf "[%s %s]\n", (char *)object_getClassName($r0),$r1
More information can be found in the Technical Note here: technotes
later xcode versions you need to call like that
expr -- (void)printf("[%s, %s]\n",(char *) object_getClassName(*(long*)($esp+4)), (char *) *(long *)($esp+8) )
If you want to limit the output to just the messages sent to one class you can add a condition like this
(int)strcmp((char*)object_getClassName($r0), "NSString")==0
If you want to log methods in the Simulator on 64 bit, use the following command instead:
expr -- (void) printf("[%s %s]\n", (char *)object_getClassName($rdi), (char *) $rsi)
Or if that doesn't work, log it this way:
The main idea is to use $rdi for the object (self), and $rsi for the selector.
A fellow developer taught me to add the same two log statements to each method. One as the first line, the other as the last line. I think he has a script that does this automatically for his projects, but the result is:
NSLog(#"<<< Entering %s >>>", __PRETTY_FUNCTION__);
NSLog(#"<<< Leaving %s >>>", __PRETTY_FUNCTION__);
At the console, this will spit out something like:
<<< Entering -[MainListTableViewController viewDidLoad] >>>
Very helpful in tracking what is going on.

google::dense_hash_map vs std::tr1::unordered_map?

I'm working on a Mobile Game for several platforms ( Android, iOS, and some maybe even some kind of console in the future ).
I'm trying to decide whether to use tr1::unordered_map or google::dense_hash_map to retrieve Textures from a Resource Manager (for later binding using OpenGL). Usually this can happen quite a few times per second (N per frame, where my Game is running at ~60 fps)
Considerations are:
Performance (memory and cpu wise)
Portability
Any ideas or suggestions are welcome.
http://attractivechaos.wordpress.com/2008/10/07/another-look-at-my-old-benchmark/
http://attractivechaos.wordpress.com/2008/08/28/comparison-of-hash-table-libraries/
go with the STL for standard containers. They have predictable behavior, and can be used seamlessly in STL algos/iterators. You're also given some performance guarantees by the STL.
This should also guarantee portability. Most compilers have the new standard implemented.
In a C++ project I developed, I was wondering something similar: which one was best, tr1:unordered_map, boost::unordered_map or std::map? I ended up declaring a typedef, controllable at compilation:
#ifdef UnorderedMapBoost
typedef boost::unordered_map<cell_key, Cell> cell_map;
#else
#ifdef UnorderedMapTR1
typedef std::tr1::unordered_map<cell_key, Cell> cell_map;
#else
typedef std::map<cell_key, Cell> cell_map;
#endif // #ifdef UnorderedMapTR1
#endif // #ifdef UnorderedMapBoost
I could then control at compile-time which one to use, and profiled it. In my case, the portability ended up being more important, so I normally use std::map.

NSLog on the device, is that a problem or must i remove that?

I have read this post: what happens to NSLog info when running on a device?
...but wondering if NSLog is a problem when distributing the app such as filling up the memory or something? I am only interested to see it when i test the consistency of my input data to the database.
The reason is that I have NSLog to control when i load the data into my database in the simulator. I could remove it when i upload but it would be good if i do not need to?
You should remove it. For example if you log contents of a UITableViewCell (in -tableView:cellForRowAtIndexPath:), it can make a big difference in performance, especially on slower hardware.
Use a macro to keep NSLog output in Debug mode, but remove it from Release mode. An example can be found on the following site: http://iphoneincubator.com/blog/debugging/the-evolution-of-a-replacement-for-nslog
I use a set of macros in my pch file that are quite handy for this.
See http://www.cimgf.com/2010/05/02/my-current-prefix-pch-file/ for details.
#ifdef DEBUG
#define DLog(...) NSLog(#"%s %#", __PRETTY_FUNCTION__, [NSString stringWithFormat:__VA_ARGS__])
#define ALog(...) [[NSAssertionHandler currentHandler] handleFailureInFunction:[NSString stringWithCString:__PRETTY_FUNCTION__ encoding:NSUTF8StringEncoding] file:[NSString stringWithCString:__FILE__ encoding:NSUTF8StringEncoding] lineNumber:__LINE__ description:__VA_ARGS__]
#else
#define DLog(...) do { } while (0)
#ifndef NS_BLOCK_ASSERTIONS
#define NS_BLOCK_ASSERTIONS
#endif
#define ALog(...) NSLog(#"%s %#", __PRETTY_FUNCTION__, [NSString stringWithFormat:__VA_ARGS__])
#endif
#define ZAssert(condition, ...) do { if (!(condition)) { ALog(__VA_ARGS__); }} while(0)
The log on the device only keeps around an hour of data, even Apple's apps log quite a few things there. So it is generally acceptable to have meaningful output in the log.
But since logging is a disk operation you might find that excessive logging slows down your app since the writing blocks the main (= UI) thread for a short while for every NSLog.
Because of this you should only log things that give more information if errors are happening in your app to facilitate finding what is going wrong.
Consider switching to cocoalumberjack, it is a drop-in replacement for NSLog and has significantly more useful functionality and better performance.
It is similar in concept to other popular logging frameworks such as log4j, yet is designed specifically for objective-c, and takes advantage of features such as multi-threading, grand central dispatch (if available), lockless atomic operations, and the dynamic nature of the objective-c runtime.
There only real reason to remove your NSLog entries is to save on memory consumption by running unnecessary code, but unless you're consistenly adding data, it shouldn't be too much of an issue.
Furthermore, if a user has an issue such as app crash, etc. NSlogs can be submitted which the dev can read to work out the reason for the crash. If you're loading the NSlog with a great deal of unnecessary data, it can be troublesome at a later date if you need to go through said log to find a user's issue in order to fix the issue.
Ultimately, I wouldn't worry too much about removing them. That's my 2 cents anyhow.