iPhone用のアプリをリリースするときに、無効NSLog();
にするとパフォーマンスが向上しますか?
12 に答える
これを行う1つの方法は、ビルド設定に移動し、デバッグ構成で次のような値を「プリプロセッサマクロ」の値に追加することです。
DEBUG_MODE=1
ベータ版またはリリース版ではなく、デバッグ構成に対してのみこれを行うようにしてください。次に、一般的なヘッダーファイルで次のようなことを行うことができます。
#ifdef DEBUG_MODE
#define DLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define DLog( s, ... )
#endif
今ではどこでもNSLog
使用する代わりに。DLog
テストとデバッグを行うと、デバッグメッセージが表示されます。ベータ版または最終リリースをリリースする準備ができると、これらのDLog
行はすべて自動的に空になり、何も出力されません。このように、変数の手動設定やNSLogs
必須のコメントはありません。ビルドターゲットを選択すると、それが処理されます。
Xcode5およびiOS7のアップデート
注:リリースビルドでprint()ステートメントを削除するXcode 7 / Swift 2.1ソリューションについては、ここで私の答えを見つけてください。
はい、リリースコードのNSLogステートメントは削除する必要があります。これは、コードの速度が低下するだけであり、リリースバージョンでは使用されないためです。幸い、Xcode 5(iOS 7)では、リリースビルドですべてのNSLogステートメントを「自動的に」削除するのは驚くほど簡単です。だから、なぜそれをしないのですか。
最初に実行する3つのステップ、次に説明
1)Xcodeプロジェクトで、「yourProjectName-prefix.pch」ファイルを見つけます(通常、これは、main.mファイルが配置されている「supportingfiles」グループの下にあります。
2)「.pch」ファイルの最後に次の3行を追加します。
#ifndef DEBUG
#define NSLog(...);
#endif
3)「デバッグ」バージョンと「リリース」バージョンの違いをテストします。これを行う1つの方法は、「スキームの編集」->「アプリ名の実行」->「情報」タブの下で、デバッグとリリースの間のドロップダウンボックスを使用して選択することです。リリースバージョンでは、デバッグコンソールにNSLog出力は表示されません。
これはどのように機能しますか?
まず第一に、プリプロセッサは比較的「ダム」であり、コンパイラが呼び出される前に「テキスト置換」として機能することを知っておく必要があります。#define
'#define'は、ステートメントに続くものに置き換えられます。
#define NSLog(...);
角かっこ()の間の(...)
「何でも」を表します。;
最後にも気をつけてください。コンパイラがこれを最適化するので、これは厳密には必要ありませんが、より「正しい」ので、そこに置くのが好きです。私たちの後#define
には「nothing」があるので、プリプロセッサはそれを「nothing」に置き換えます。したがって、NSLog...
までから始まり、を含む完全な行を破棄し;
ます。
#ifdef
定義ステートメントは、(定義されている場合)または#ifndef
(定義されていない場合)を使用して条件付きにすることができます
ここでは#ifndef DEBUG
、を記述します。これは、「シンボルDEBUGが定義されていない場合」を意味します。#ifdef
または#ifndef
を「閉じる」必要があります#endif
Xcode 5は、デフォルトで、ビルドモードが「DEBUG」の場合に「DEBUG」シンボルを定義します。「リリース」では、これは定義されていません。これは、プロジェクト設定の[ビルド設定]タブで確認できます->[AppleLLVM5.0-前処理]->[プリプロセッサマクロ]セクションまでスクロールダウンします。シンボル「DEBUG」がリリースビルド用に定義されていないことがわかります。
最後に、.pchファイルはXcodeによって自動的に作成され、コンパイル時にすべてのソースファイルに自動的に含まれます。つまり、すべて#define
を各ソースファイルに入れたかのようです。
上記のほとんどすべての回答は解決策を示していますが、問題を説明していません。グーグルで検索して、理由を見つけました。これが私の答えです:
はい、リリースバージョンでNSLogをコメントアウトすると、パフォーマンスが向上します。NSLogはかなり遅いからです。なんで?NSLogは2つのことを行います。1)Apple System Logging(ASL)にログメッセージを書き込みます。2)アプリがxcodeで実行されている場合は、stderrにも書き込みます。
主な問題は最初の問題にあります。スレッドセーフを実現するために、NSLogが呼び出されるたびに、ASLファシリティへの接続を開き、メッセージを送信して、接続を閉じます。接続操作は非常に高価です。もう1つの理由は、NSLogがログに記録するタイムスタンプを取得するためにある程度の時間を費やしていることです。
ここからの参照。
私の個人的なお気に入りは、可変個引数マクロを使用することです。
#ifdef NDEBUG
#define NSLog(...) /* suppress NSLog when in release mode */
#endif
NSLog()
本番環境でまったく電話をかけない方が少し速くなると賢明にコメントしたすべての人に加えて、次のことを追加します。
これらのNSLog()
出力文字列はすべて、ストアからアプリをダウンロードし、Xcodeを実行しているMacにデバイスを接続して(オーガナイザーウィンドウから)実行するすべての人に表示されます。
ログに記録する情報によっては(特に、アプリがサーバーに接続したり、認証を行ったりする場合)、これは重大なセキュリティ問題になる可能性があります。
Xcodeのプロジェクトの現在のデフォルト設定内で、NS_BLOCK_ASSERTIONS
マクロはリリースバージョンとDEBUG=1
デバッグバージョンで1に設定されます。
だから、私は次の方法を好みます。
// NS_BLOCK_ASSERTIONS is defined by default, as shown in the screenshot above.
// Or, you can define yourself Flags in the `Other C Flags` -> `Release`.
#ifndef NS_BLOCK_ASSERTIONS
#define _DEBUG
#endif
#ifdef _DEBUG
// for debug mode
#define DLog(fmt,...) NSLog(@"%s " fmt, __FUNCTION, ##__VA_ARGS__)
... /// something extra
#else
// for release mode
#define DLog(fmt,...) /* throw it away */
... /// something extra
#endif
はい、無効にする必要があります。特に、コードの速度を最大化しようとしている場合。左右にNSLを記録すると、他の開発者が掘り下げようとしている可能性のあるシステムログが汚染され、速度が重要なコード(ループ内など)に大きな影響を与える可能性があります。 「速度が30%向上」したアップデートをリリースする必要があります。数週間後...;-)
すべての良い答えですが、主にアプリの開発/テスト段階で使用することを検討できるもう1つの小さなトリックがあります。
また、コードの直接制御外の問題を示す可能性のあるメッセージではなく、デバッグコードのみをオフにしたい場合は、アプリのリリースコードにも役立ちます。
トリック:
.mファイルの先頭に次の行を含めるだけで、.mファイルごとのNSLogをオフにできます。
#define NSLog(...)
(注:これを.hファイルに入れないでください。.mファイルのみに入れてください!)
これにより、コンパイラはNSLog()
代わりにプリプロセッサマクロを展開して評価します。マクロは引数を取り除くだけです。
もう一度オンにしたい場合は、いつでも使用できます
#undef NSLog
たとえば、次のようなことを行うことで、特定のメソッドグループの周りでNSLogが呼び出されないようにすることができます。
#define NSLog(...)
-(void) myProblematicMethodThatSometimesNeedsDebugging {
...
}
#undef NSLog
NSLogは低速であるため、リリースビルドには使用しないでください。以下のような単純なマクロは、無効にする必要のあるアサーションとともに無効にします。リリースビルドでNSLogが必要になる、あまり一般的ではないケースでは、直接呼び出すだけです。「その他のcフラグ」ビルド設定に「-DNDEBUG」を追加することを忘れないでください。
#ifdef NDEBUG
#define MYLog(f, ...)
#else
#define MYLog(f, ...) NSLog(f, ## __VA_ARGS__)
#endif
pchファイルで#endifの前にこれを書き留めます
#define NSLog() //
これはどうですか?
#ifndef DEBUG_MODE
fclose(stderr); // the simplest way to disable output from NSLog
#endif
var showDebugLogs = false;
func DLog(format: String, args: CVarArgType...) {
if showDebugLogs{
println(String(format: format, arguments: args))
}
}
これは追加の引数も受け入れます。必要に応じて、showDebugLogsパラメーター値をtrueまたはfalseに設定するだけです。