새로운 자동 참조 계산 메커니즘은 어떻게 작동합니까?


206

누군가가 ARC 작동 방식을 간략하게 설명 할 수 있습니까? 가비지 수집과는 다르다는 것을 알고 있지만 그것이 어떻게 작동하는지 정확히 궁금했습니다.

또한 ARC가 성능을 방해하지 않고 GC의 기능을 수행하는 경우 Java가 GC를 사용하는 이유는 무엇입니까? 왜 ARC도 사용하지 않습니까?


2
이것은 모든 그것에 대해 당신을 말할 것이다 : http://clang.llvm.org/docs/AutomaticReferenceCounting.html 이 엑스 코드에서 구현 것 방법 및 iOS 5는 NDA을 받고있다.
Morten Fast

14
@mbehan 그것은 좋지 않은 조언입니다. iOS 개발자 센터에 로그인하거나 계정을 갖고 싶지 않지만 그럼에도 불구하고 ARC에 대해 알고 싶습니다.
Andres F.

1
ARC는 GC의 모든 기능을 수행하지 않으며 강력하고 약한 참조 시맨틱으로 명시 적으로 작업해야하며 올바른 권한을 얻지 못하면 메모리가 누출됩니다. 내 경험상 Objective-C에서 블록을 사용할 때 처음에는 까다 롭고 트릭을 알게 된 후에도 많은 블록 사용에 대해 성가신 (IMO) 상용구 코드가 남아 있습니다. 강력하고 약한 참조를 잊어 버리는 것이 더 편리합니다. 또한 GC는 ARC wrt보다 약간 더 나은 성능을 발휘할 수 있습니다. CPU이지만 더 많은 메모리가 필요합니다. 메모리가 많은 경우 명시 적 메모리 관리보다 빠를 수 있습니다.
TaylanUB

@TaylanUB : "더 많은 메모리가 필요합니다". 많은 사람들이 그렇게 말하지만 나는 믿기가 어렵습니다.
Jon Harrop

2
@ JonHarrop : 현재 솔직히 말한 이유를 기억하지 못합니다. :-) 그 사이에 GC 전략이 너무 많다는 것을 깨달았습니다. Hans Boehm의 기억 할당 신화와 반진에서 다음과 같이 이야기하겠습니다 . "왜이 지역이 모호한 민속 지혜에 빠지기 쉬운가?"
TaylanUB

답변:


244

Objective-C를 사용하는 모든 새로운 개발자는 객체를 유지, 릴리스 및 자동 릴리스 할 때의 엄격한 규칙을 배워야합니다. 이 규칙은 메소드에서 반환 된 객체의 보유 수를 의미하는 명명 규칙도 지정합니다. Objective-C의 메모리 관리는 이러한 규칙을 마음에 새기고 일관성있게 적용하면 제 2의 자연이되지만, 가장 경험이 많은 Cocoa 개발자들도 때때로 미끄러집니다.

CLL 정적 분석기를 사용하여 LLVM 개발자는 이러한 규칙이 코드의 경로 내에서 메모리 누수 및 초과 릴리스를 지적 할 수있는 도구를 작성할 수있을 정도로 신뢰할 수 있음을 깨달았습니다.

ARC ( Automatic Reference Counting )는 다음 논리적 단계입니다. 컴파일러가 객체를 유지하고 해제 해야하는 위치를 인식 할 수 있다면 왜 해당 코드를 삽입하지 않습니까? 엄밀하고 반복적 인 작업은 컴파일러와 그 형제가 잘하는 것입니다. 인간은 일을 잊고 실수를하지만 컴퓨터는 훨씬 일관성이 있습니다.

그러나이 플랫폼에서 메모리 관리에 대해 걱정할 필요는 없습니다. 나는 내 대답에 (사이클을 유지) 조심 기본 문제에 대한 설명이 여기에 약한 포인터를 표시하기 위해 당신의 부분에 약간의 생각을 필요로 할 수있는. 그러나 ARC에서 얻는 것과 비교하면 미미합니다.

수동 메모리 관리 및 가비지 수집과 비교할 때 ARC는 유지 / 릴리스 코드를 작성하지 않아도되지만 가비지 수집 환경에서 정지 및 톱니 메모리 프로파일이 없어 두 가지 이점을 모두 제공합니다. 가비지 콜렉션이 갖는 장점의 장점은 유지주기를 처리하는 기능과 원자 속성 할당이 저렴하다는 사실입니다 ( 여기 에서 논의 됨 ). 기존의 모든 Mac GC 코드를 ARC 구현으로 교체하고 있음을 알고 있습니다.

이것이 다른 언어로 확장 될 수 있는지에 관해서는 Objective-C의 참조 계산 시스템을 중심으로 이루어졌습니다. 이것을 Java 또는 다른 언어에 적용하는 것이 어려울 수 있지만, 저수준 컴파일러 세부 사항에 대해 결정적인 진술을하기에 충분하지 않습니다. 애플이 LLVM에서 이러한 노력을 추진하고있는 것을 감안할 때, Objective-C는 다른 당사자가 자신의 상당한 자원을 커밋하지 않는 한 먼저 나올 것입니다.

WWDC에서이 충격적인 개발자가 공개되었으므로 사람들은 이와 같은 일을 할 수 있다는 것을 알지 못했습니다. 시간이 지남에 따라 다른 플랫폼에 나타날 수 있지만 현재로서는 LLVM 및 Objective-C에만 적용됩니다.


56
강조점 : 메모리 관리에 대해 걱정할 필요가 없습니다.
bshirley

6
ARC는 정말로 혁신인가? 귀하의 답변에서 ARC는 Objective-C에서 처음으로 사용되는 새로운 개념이라고 결론 내립니다 (잘못된 경우 수정하십시오). 솔직히 말해서, 나는 Objective-C 개발자가 아니며 ARC에 대해 잘 모르지만 Boost Shared Pointers (boost.org 참조)는 정확히 같은 것이 아닙니까? 그렇지 않은 경우 차이점은 무엇입니까?
theDmi

2
@DMM-Boost처럼 오버로드 된 연산자에 의존하기보다는 컴파일러 수준의 프로세스로 전체 언어로 확장됩니다. 그 중에서도 수동으로 참조 카운트 된 응용 프로그램을 ARC로 쉽게 변환 할 수 있습니다. Boost는 또한 ARC와 달리 로컬 변수를 처리 할 수 ​​있습니다. ARC는 로컬 변수가 더 이상 사용되지 않고 그 시점에서 해제 될 수있는 순간을 알고 있습니다. Boost를 사용하면 변수로 수행 할 수있는 방법을 지정해야한다고 생각합니다.
Brad Larson

6
델파이는 "새로운 것"이라는 질문에 답하기 위해 10 년 넘게 문자열, 배열 및 인터페이스 (COM 지원용)에 대한 자동 참조 카운트를 수행했습니다. 나는 그것이 gc'd 환경과 "수동으로 수행"환경 사이에서 정말 좋은 절충안이라는 것에 동의한다. ObjC와 LLVM에있어서 기쁩니다 (따라서 다른 언어도 활용할 수 있습니다).
davidmw 2016 년

2
@theDmi : "ARC는 정말 혁신적입니까?" 자동 참조 카운팅은 1960 년에 발명되었으며 Python 및 Mathematica와 같은 많은 언어에서 사용되었습니다. JVM 또는 CLR에서는 속도가 느리고 누수주기 때문에 사용되지 않습니다.
Jon Harrop

25

ARC는 컴파일러가 유지 / 릴리스를 호출 할시기를 파악하여 구 유지 / 릴리스 (MRC)를 재생합니다. GC 시스템보다 성능이 높고 피크 메모리 사용이 적으며 예측 가능한 성능이 더 높습니다.

반면에 ARC (또는 MRC)에서는 일부 유형의 데이터 구조가 불가능하지만 GC는이를 처리 할 수 ​​있습니다.

예를 들어 node라는 클래스가 있고 node에 NSArray의 자식이 있고 GC와 함께 작동하는 부모에 대한 단일 참조가있는 경우. ARC (및 수동 참조 카운팅)를 사용하면 문제가 있습니다. 주어진 노드는 자식 노드와 부모 노드에서 참조됩니다.

처럼:

A -> [B1, B2, B3]
B1 -> A, B2 -> A, B3 -> A

A를 사용하는 동안 (예 : 지역 변수를 통해) 모두 괜찮습니다.

그것으로 (B1 / B2 / B3) 끝났 으면 GC 시스템은 결국 스택과 CPU 레지스터에서 찾을 수있는 모든 것을보기로 결정합니다. A, B1, B2, B3을 찾지 않으므로이를 마무리하고 메모리를 다른 개체로 재활용합니다.

ARC 또는 MRC를 사용하고 A로 마무리하면 참조 횟수가 3이고 (B1, B2 및 B3은 모두 참조) B1 / B2 / B3은 모두 참조 카운트가 1입니다 (A의 NSArray는 마다). 따라서 아무 것도 사용할 수 없어도 모든 객체는 계속 작동합니다.

일반적인 해결책은 이러한 참조 중 하나가 약해야한다는 것을 결정하는 것입니다 (참조 횟수에 영향을 미치지 않음). 예를 들어 A를 통해서만 B1 / B2 / B3을 참조하는 경우와 같이 일부 사용 패턴에서는 작동합니다. 그러나 다른 패턴에서는 실패합니다. 예를 들어, 때때로 B1을 붙잡고 부모 포인터를 통해 위로 올라가서 A를 찾길 기대하는 경우 B1 만 잡고 있으면 참조가 약한 참조로 A가 증발하고 B2와 B3을 취할 수 있습니다 그것으로.

때때로 이것은 문제가되지 않지만 복잡한 데이터 구조로 작업하는 매우 유용하고 자연스러운 방법은 ARC / MRC와 함께 사용하기가 매우 어렵습니다.

따라서 ARC는 GC 목표와 같은 종류의 문제를 목표로합니다. 그러나 ARC는 GC보다 더 제한된 사용 패턴 세트에서 작동하므로 Java와 같은 GC 언어를 가져 와서 ARC와 같은 것을 접목하면 일부 프로그램이 더 이상 작동하지 않습니다 (또는 적어도 버려진 메모리의 톤을 생성합니다) 심각한 스와핑 문제가 발생하거나 메모리 또는 스왑 공간이 부족할 수 있습니다.

또한 ARC는 성능 (또는 예측 가능성)에 더 큰 우선 순위를 두는 반면 GC는 일반적인 솔루션에 더 큰 우선 순위를 둡니다. 결과적으로 GC는 CPU / 메모리 요구를 예측할 수없고 ARC보다 성능이 낮지 만 (일반적으로) 사용 패턴을 처리 할 수 ​​있습니다. ARC는 많은 일반적인 사용 패턴에서 훨씬 잘 작동하지만 몇 가지 (유효한) 사용 패턴에서는 넘어져서 죽습니다.


"반면에 어떤 유형의 데이터 구조는 ARC로는 불가능합니다."힌트 없이는 자동 정리가 불가능하다는 의미입니다. 분명히 데이터 구조가 있습니다.
Steven Fisher

물론 ARC에서는 ObjC 객체의 자동 정리 만 사용할 수 있으므로 "자동 정리 없음"== "정리 없음"입니다. 그래도 시간이 더 있으면 대답 해 드리겠습니다.
Stripes

@Stripes : ARC에서 수동 정리에 해당하는 것은주기를 수동으로 차단하는 것입니다 foo = nil.
더글러스

"[ARC]는 성능이 더 높은 경향이 있습니다 ... ARC는 성능에 더 큰 우선 순위를 둡니다". 참조 카운트가 가비지 수집 추적보다 훨씬 느리다 는 것이 잘 알려진 사실에 놀랐습니다 . flyingfrogblog.blogspot.co.uk/2011/01/…
Jon Harrop

2
이론적으로 GC는 더 빠릅니다 (각 참조 카운트 조작은 다중 프로세서 캐시 코 히어 런트이어야하고 많은 것이 있습니다). 실제로 ObjC에 사용 가능한 유일한 GC 시스템은 훨씬 느립니다. 또한 GC 시스템이 사용자가 인식 할 수있는 시간 동안 임의의 시간에 스레드를 일시 중지하는 것은 매우 일반적입니다 (실시간 GC 시스템이 있지만 공통적이지 않으며 "관심있는"제약 조건이 있다고 생각합니다)
Stripes

4

마법

그러나 더 구체적으로 ARC는 코드로 수행 할 작업을 정확하게 수행하여 작동합니다 (특정 사소한 차이가 있음). ARC는 런타임이며 GC와 달리 컴파일 타임 기술로 성능에 부정적인 영향을 미칩니다. ARC는 객체에 대한 참조를 추적하고 일반적인 규칙에 따라 유지 / 해제 / 자동 해제 방법을 합성합니다. 이로 인해 ARC는 더 이상 필요하지 않은 즉시 컨벤션을 위해 자동 릴리즈 풀에 넣는 대신 릴리즈 할 수 있습니다.

다른 개선점으로는 제로 약한 참조, 힙에 자동 블록 복사, 보드 전체의 속도 향상 (자동 릴리스 풀의 경우 6 배)이 있습니다.

이 모든 작동 방식에 대한 자세한 내용은 LLVM Docs on ARC 에서 찾을 수 있습니다.


2
-1 "ARC는 런타임이고 GC와 달리 컴파일 타임 기술이며 성능에 부정적인 영향을 미칩니다." 참조 카운트는 런타임에 충돌하여 매우 비효율적입니다. 따라서 JVM 및 .NET과 같은 GC 추적이 훨씬 빠릅니다.
Jon Harrop

1
@ 존 : 당신은 이것에 대한 증거가 있습니까? 필자가 읽은 바에 따르면 새로운 RC 알고리즘은 일반적으로 M & S GC보다 성능이 우수하거나 더 나은 것으로 보입니다.
xryl669

1
@ xryl669 : GC 핸드북 ( gchandbook.org )에 자세한 설명이 있습니다 . 추적! = M & S입니다.
Jon Harrop

3

가비지 수집과 크게 다릅니다. 다른 라인에서 물체가 누출 될 수 있다는 경고 메시지를 보셨습니까? 이 문장들은 심지어 당신이 객체를 어떤 라인에 할당했는지 알려줍니다. 이것은 한 걸음 더 나아 갔으며 이제는 거의 100 %의 시간에 대부분의 프로그래머보다 더 나은 적절한 위치에 retain/ release문을 삽입 할 수 있습니다 . 간혹 도움이 필요한 일부 유지 된 개체 인스턴스가있을 수 있습니다.


0

Apple 개발자 문서에 잘 설명되어 있습니다. "ARC 작동 방식"을 읽으십시오

인스턴스가 여전히 필요한 동안 사라지지 않도록 ARC는 현재 각 클래스 인스턴스를 참조하는 속성, 상수 및 변수의 수를 추적합니다. ARC는 해당 인스턴스에 대한 하나 이상의 활성 참조가 여전히 존재하는 한 인스턴스 할당을 해제하지 않습니다.

인스턴스가 여전히 필요한 동안 사라지지 않도록 ARC는 현재 각 클래스 인스턴스를 참조하는 속성, 상수 및 변수의 수를 추적합니다. ARC는 해당 인스턴스에 대한 하나 이상의 활성 참조가 여전히 존재하는 한 인스턴스 할당을 해제하지 않습니다.

Diff를 아는 것. 쓰레기 수집 및 ARC 사이 : 읽기


0

ARC는 객체의 자동 메모리 관리를 제공하는 컴파일러 기능입니다.

retain, release, 및 을 사용해야 할 때를 기억할 필요없이 autoreleaseARC는 객체의 수명 요구 사항을 평가하고 컴파일 타임에 자동으로 적절한 메모리 관리 호출을 삽입합니다. 컴파일러는 또한 적절한 할당 해제 방법을 생성합니다.

컴파일러 retain/release는 컴파일 타임에 필요한 호출을 삽입 하지만 이러한 호출은 다른 코드와 마찬가지로 런타임에 실행됩니다.

다음 다이어그램은 ARC 작동 방식에 대한 이해를 돕기위한 것입니다.

여기에 이미지 설명을 입력하십시오

iOS 개발에 처음이고 Objective C에 대한 경험이없는 사람들. 메모리 관리에 대한 이해를 높이려면 Apple의 고급 메모리 관리 프로그래밍 안내서 를 참조하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.