120

iPhone用のアプリをリリースするときに、無効NSLog();にするとパフォーマンスが向上しますか?

4

12 に答える 12

128

これを行う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必須のコメントはありません。ビルドターゲットを選択すると、それが処理されます。

于 2010-01-08T05:40:40.793 に答える
119

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を各ソースファイルに入れたかのようです。

于 2014-01-26T16:57:20.447 に答える
34

上記のほとんどすべての回答は解決策を示していますが、問題を説明していません。グーグルで検索して、理由を見つけました。これが私の答えです:

はい、リリースバージョンでNSLogをコメントアウトすると、パフォーマンスが向上します。NSLogはかなり遅いからです。なんで?NSLogは2つのことを行います。1)Apple System Logging(ASL)にログメッセージを書き込みます。2)アプリがxcodeで実行されている場合は、stderrにも書き込みます。

主な問題は最初の問題にあります。スレッドセーフを実現するために、NSLogが呼び出されるたびに、ASLファシリティへの接続を開き、メッセージを送信して、接続を閉じます。接続操作は非常に高価です。もう1つの理由は、NSLogがログに記録するタイムスタンプを取得するためにある程度の時間を費やしていることです。

ここからの参照。

于 2013-07-19T05:27:15.287 に答える
23

私の個人的なお気に入りは、可変個引数マクロを使用することです。

#ifdef NDEBUG
    #define NSLog(...) /* suppress NSLog when in release mode */
#endif
于 2013-01-11T00:17:28.563 に答える
21

NSLog()本番環境でまったく電話をかけない方が少し速くなると賢明にコメントしたすべての人に加えて、次のことを追加します。

これらのNSLog()出力文字列はすべて、ストアからアプリをダウンロードし、Xcodeを実行しているMacにデバイスを接続して(オーガナイザーウィンドウから)実行するすべての人に表示されます。

ログに記録する情報によっては(特に、アプリがサーバーに接続したり、認証を行ったりする場合)、これは重大なセキュリティ問題になる可能性があります

于 2013-12-03T05:55:48.237 に答える
14

プロジェクトのデフォルト設定

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
于 2011-12-27T02:45:56.073 に答える
5

はい、無効にする必要があります。特に、コードの速度を最大化しようとしている場合。左右にNSLを記録すると、他の開発者が掘り下げようとしている可能性のあるシステムログが汚染され、速度が重要なコード(ループ内など)に大きな影響を与える可能性があります。 「速度が30%向上」したアップデートをリリースする必要があります。数週間後...;-)

于 2010-01-08T04:36:25.207 に答える
5

すべての良い答えですが、主にアプリの開発/テスト段階で使用することを検討できるもう1つの小さなトリックがあります。

また、コードの直接制御外の問題を示す可能性のあるメッセージではなく、デバッグコードのみをオフにしたい場合は、アプリのリリースコードにも役立ちます。

トリック:

.mファイルの先頭に次の行を含めるだけで、.mファイルごとのNSLogをオフにできます

#define NSLog(...)

注:これを.hファイルに入れないでください。.mファイルのみに入れてください!

これにより、コンパイラはNSLog()代わりにプリプロセッサマクロを展開して評価します。マクロは引数を取り除くだけです。

もう一度オンにしたい場合は、いつでも使用できます

#undef NSLog

たとえば、次のようなことを行うことで、特定のメソッドグループの周りでNSLogが呼び出されないようにすることができます。

#define NSLog(...)
-(void) myProblematicMethodThatSometimesNeedsDebugging {
    ...
}
#undef NSLog
于 2013-10-09T00:35:27.820 に答える
3

NSLogは低速であるため、リリースビルドには使用しないでください。以下のような単純なマクロは、無効にする必要のあるアサーションとともに無効にします。リリースビルドでNSLogが必要になる、あまり一般的ではないケースでは、直接呼び出すだけです。「その他のcフラグ」ビルド設定に「-DNDEBUG」を追加することを忘れないでください。

#ifdef NDEBUG
#define MYLog(f, ...) 
#else
#define MYLog(f, ...) NSLog(f, ## __VA_ARGS__)
#endif
于 2010-01-17T05:53:55.193 に答える
2

pchファイルで#endifの前にこれを書き留めます

#define NSLog() //
于 2013-09-25T05:28:18.047 に答える
0

これはどうですか?

#ifndef DEBUG_MODE
        fclose(stderr);     // the simplest way to disable output from NSLog
#endif    
于 2012-02-15T19:48:00.687 に答える
0
var showDebugLogs = false;

    func DLog(format: String, args: CVarArgType...) {
        if showDebugLogs{
        println(String(format: format, arguments: args))
        }
    }

これは追加の引数も受け入れます。必要に応じて、showDebugLogsパラメーター値をtrueまたはfalseに設定するだけです。

于 2015-06-02T09:42:40.863 に答える