iPhone 용 앱을 출시 할 때 비활성화 NSLog();
하면 성능이 향상됩니까?
NSLog()
앱 전체에 걸쳐 얼마나 많은지에 따라 다릅니다 . NSLog()
실행하는 데 시간이 걸리고 앱 런타임에 추가 오버 헤드가 추가됩니다. 어쨌든 간단한 DEBUG 전 처리기 매크로로 성능에 도움이된다면 비활성화해야합니다.
iPhone 용 앱을 출시 할 때 비활성화 NSLog();
하면 성능이 향상됩니까?
NSLog()
앱 전체에 걸쳐 얼마나 많은지에 따라 다릅니다 . NSLog()
실행하는 데 시간이 걸리고 앱 런타임에 추가 오버 헤드가 추가됩니다. 어쨌든 간단한 DEBUG 전 처리기 매크로로 성능에 도움이된다면 비활성화해야합니다.
답변:
이를 수행하는 한 가지 방법은 빌드 설정으로 이동하여 디버그 구성에서 다음과 같은 "전 처리기 매크로"값에 값을 추가하는 것입니다.
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
필요한 주석을 달 필요가 없습니다. 빌드 대상을 선택하면 처리됩니다.
Xcode 5 및 iOS 7 업데이트
참고 : 릴리스 빌드에서 print () 문 을 제거 하는 Xcode 7 / Swift 2.1 솔루션의 경우 여기에서 내 대답을 찾으 십시오 .
예, 릴리스 코드에서 NSLog 문을 제거해야합니다. 이는 코드 속도를 늦추고 릴리스 버전에서는 사용하지 않기 때문입니다. 다행히 Xcode 5 (iOS 7)에서는 릴리스 빌드에서 모든 NSLog 문을 '자동'으로 제거하는 것이 놀랍도록 간단합니다. 그러니 왜 그렇게하지 마십시오.
먼저 취해야 할 3 단계, 다음 몇 가지 설명
1) Xcode 프로젝트에서 'yourProjectName-prefix.pch'파일을 찾습니다 (일반적으로 main.m 파일이있는 'supporting files'그룹에서 찾을 수 있습니다.
2) '.pch'파일 끝에 다음 3 줄을 추가합니다.
#ifndef DEBUG
#define NSLog(...);
#endif
3) '디버그'와 '출시'버전의 차이점을 테스트하십시오. 이를 수행하는 한 가지 방법은 '구성표 편집'-> '앱 이름 실행'-> '정보'탭에서 디버그와 릴리스 사이의 드롭 다운 상자를 사용하여 선택하는 것입니다. 릴리스 버전에서는 디버그 콘솔에 NSLog 출력이 표시되지 않습니다!
이 모든 것이 어떻게 작동합니까?
우선, 전처리 기가 상대적으로 '멍청한'것이고 컴파일러가 호출되기 전에 '텍스트 대체자'역할을한다는 것을 알아야합니다. '#define'은 #define
명령문 뒤에 오는 것으로 대체 합니다.
#define NSLog(...);
는 (...)
괄호 사이에 '무엇이든'()를 의미합니다. ;
끝에 도 마음 . 이것은 컴파일러가 이것을 최적화하기 때문에 꼭 필요한 것은 아니지만 더 '정확'하기 때문에 거기에 두는 것을 좋아합니다. 우리의 후 #define
처리기가 '아무것도'로 대체됩니다, 그래서 그것은 단지에서 시작하여 전체 라인을 버리지 않도록, '아무것도'없다 NSLog...
때까지와를 포함 ;
.
define 문은 #ifdef
(정의 된 경우) 또는 #ifndef
(정의되지 않은 경우 )를 사용하여 조건부로 만들 수 있습니다.
여기서 우리 #ifndef DEBUG
는 '디버그 기호가 정의되지 않은 경우'를 의미합니다. #ifdef
또는 #ifndef
될 필요가와 '폐쇄'#endif
Xcode 5는 기본적으로 빌드 모드가 'DEBUG'일 때 'DEBUG'기호를 정의합니다. '릴리스'에서는 정의되지 않았습니다. 프로젝트 설정에서 '빌드 설정'탭-> 'Apple LLVM 5.0-전처리'섹션으로 스크롤-> 전 처리기 매크로에서이를 확인할 수 있습니다. 릴리스 빌드에 대해 'DEBUG'기호가 정의되지 않았 음을 알 수 있습니다!
마지막으로 .pch 파일은 Xcode에 의해 자동으로 생성되며 컴파일 시간 동안 모든 소스 파일에 자동으로 포함됩니다. 따라서 #define
각 소스 파일에 모든 것을 넣은 것과 같습니다 .
NSLog
.
NSLog
예를 들면, DO 아무것도 문으로 if(AllCool) NSLog(@"Cool!Do Nothing!"); else...
대신 팝업 NSLog
일부 중괄호if(AllCool) {NSLog(@"Cool!Do Nothing!");} else...
위의 거의 모든 답변은 해결책을 제시하지만 문제를 설명하지는 않습니다. 나는 구글에서 검색을했고 그 이유를 찾았다. 내 대답은 다음과 같습니다.
예, 릴리스 버전에서 NSLog를 주석 처리하면 성능이 향상됩니다. NSLog는 매우 느리기 때문입니다. 왜? NSLog는 1) Apple System Logging (ASL)에 로그 메시지를 기록하고, 2) 앱이 xcode에서 실행되는 경우 stderr에도 기록합니다.
주요 문제는 첫 번째 문제에 있습니다. 스레드 안전을 달성하기 위해 NSLog가 호출 될 때마다 ASL 시설에 대한 연결을 열고 메시지를 보내고 연결을 닫습니다. 연결 작업은 매우 비쌉니다. 또 다른 이유는 NSLog가 기록 할 타임 스탬프를 가져 오는 데 시간을 소비하기 때문입니다.
여기 에서 참조 .
개인적으로 가장 좋아하는 것은 가변 매크로를 사용하는 것입니다.
#ifdef NDEBUG
#define NSLog(...) /* suppress NSLog when in release mode */
#endif
NSLog()
프로덕션에서 전혀 전화하지 않는 것이 약간 더 빠르게 실행 된다는 현명하게 언급 한 모든 사람들과 더불어 다음과 같이 추가 하겠습니다.
이러한 모든 NSLog()
출력 문자열은 스토어에서 앱을 다운로드하고 Xcode를 실행하는 Mac에 연결된 장치로 실행하는 모든 사람에게 표시됩니다 (Organizer 창을 통해).
기록하는 정보에 따라 (특히 앱이 서버에 연결하거나 인증하는 경우 등) 심각한 보안 문제가 될 수 있습니다 .
print()
모르겠지만 대부분 그럴 것입니다.
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
모든 좋은 대답이 있지만 여기에 주로 앱의 개발 / 테스트 단계에서 사용할 수있는 또 다른 작은 트릭이 있습니다.
또한 코드의 직접 제어를 벗어난 문제를 나타낼 수있는 메시지가 아닌 디버그 코드 만 설정하려는 경우 앱 릴리스 코드에도 유용 할 수 있습니다.
트릭 :
.m 파일 상단에 다음 줄을 포함하여 .m 파일 당 NSLog를 끌 수 있습니다 .
#define NSLog(...)
( 참고 : 않는 NOT 만하는 .m 파일을 이것을 .H 파일을 넣어! )
이렇게하면 컴파일러가 NSLog()
대신 전 처리기 매크로를 확장하여 평가 합니다. 매크로는 인수를 제거하는 것 외에는 수행하지 않습니다.
다시 켜고 싶다면 언제든지 사용할 수 있습니다.
#undef NSLog
예를 들어 다음과 같은 작업을 수행하여 특정 메서드 그룹에 대한 NSLog 호출을 방지 할 수 있습니다.
#define NSLog(...)
-(void) myProblematicMethodThatSometimesNeedsDebugging {
...
}
#undef 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로 설정합니다.
Dlog
함수에 전달 된 인수를 계산하는 오버 헤드 (및 잠재적 인 부작용)의 문제가 있습니다.