누군가가 ARC 작동 방식을 간략하게 설명 할 수 있습니까? 가비지 수집과는 다르다는 것을 알고 있지만 그것이 어떻게 작동하는지 정확히 궁금했습니다.
또한 ARC가 성능을 방해하지 않고 GC의 기능을 수행하는 경우 Java가 GC를 사용하는 이유는 무엇입니까? 왜 ARC도 사용하지 않습니까?
누군가가 ARC 작동 방식을 간략하게 설명 할 수 있습니까? 가비지 수집과는 다르다는 것을 알고 있지만 그것이 어떻게 작동하는지 정확히 궁금했습니다.
또한 ARC가 성능을 방해하지 않고 GC의 기능을 수행하는 경우 Java가 GC를 사용하는 이유는 무엇입니까? 왜 ARC도 사용하지 않습니까?
답변:
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에만 적용됩니다.
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는 많은 일반적인 사용 패턴에서 훨씬 잘 작동하지만 몇 가지 (유효한) 사용 패턴에서는 넘어져서 죽습니다.
foo = nil
.
마법
그러나 더 구체적으로 ARC는 코드로 수행 할 작업을 정확하게 수행하여 작동합니다 (특정 사소한 차이가 있음). ARC는 런타임이며 GC와 달리 컴파일 타임 기술로 성능에 부정적인 영향을 미칩니다. ARC는 객체에 대한 참조를 추적하고 일반적인 규칙에 따라 유지 / 해제 / 자동 해제 방법을 합성합니다. 이로 인해 ARC는 더 이상 필요하지 않은 즉시 컨벤션을 위해 자동 릴리즈 풀에 넣는 대신 릴리즈 할 수 있습니다.
다른 개선점으로는 제로 약한 참조, 힙에 자동 블록 복사, 보드 전체의 속도 향상 (자동 릴리스 풀의 경우 6 배)이 있습니다.
이 모든 작동 방식에 대한 자세한 내용은 LLVM Docs on ARC 에서 찾을 수 있습니다.
가비지 수집과 크게 다릅니다. 다른 라인에서 물체가 누출 될 수 있다는 경고 메시지를 보셨습니까? 이 문장들은 심지어 당신이 객체를 어떤 라인에 할당했는지 알려줍니다. 이것은 한 걸음 더 나아 갔으며 이제는 거의 100 %의 시간에 대부분의 프로그래머보다 더 나은 적절한 위치에 retain
/ release
문을 삽입 할 수 있습니다 . 간혹 도움이 필요한 일부 유지 된 개체 인스턴스가있을 수 있습니다.
Apple 개발자 문서에 잘 설명되어 있습니다. "ARC 작동 방식"을 읽으십시오
인스턴스가 여전히 필요한 동안 사라지지 않도록 ARC는 현재 각 클래스 인스턴스를 참조하는 속성, 상수 및 변수의 수를 추적합니다. ARC는 해당 인스턴스에 대한 하나 이상의 활성 참조가 여전히 존재하는 한 인스턴스 할당을 해제하지 않습니다.
인스턴스가 여전히 필요한 동안 사라지지 않도록 ARC는 현재 각 클래스 인스턴스를 참조하는 속성, 상수 및 변수의 수를 추적합니다. ARC는 해당 인스턴스에 대한 하나 이상의 활성 참조가 여전히 존재하는 한 인스턴스 할당을 해제하지 않습니다.
Diff를 아는 것. 쓰레기 수집 및 ARC 사이 : 읽기 이
ARC는 객체의 자동 메모리 관리를 제공하는 컴파일러 기능입니다.
retain, release
, 및 을 사용해야 할 때를 기억할 필요없이 autorelease
ARC는 객체의 수명 요구 사항을 평가하고 컴파일 타임에 자동으로 적절한 메모리 관리 호출을 삽입합니다. 컴파일러는 또한 적절한 할당 해제 방법을 생성합니다.
컴파일러 retain/release
는 컴파일 타임에 필요한 호출을 삽입 하지만 이러한 호출은 다른 코드와 마찬가지로 런타임에 실행됩니다.
다음 다이어그램은 ARC 작동 방식에 대한 이해를 돕기위한 것입니다.
iOS 개발에 처음이고 Objective C에 대한 경험이없는 사람들. 메모리 관리에 대한 이해를 높이려면 Apple의 고급 메모리 관리 프로그래밍 안내서 를 참조하십시오 .