2009-08-22 5 views
6

C#에서 많은 이터레이터를 사용하여 메모리 사용에 미치는 영향은 무엇입니까? 수천 개의 foreach 루프를 수행하는 프로그램을 가정 해 봅시다. 각 루프는 GetEnumerator을 호출하여 힙에 임시 개체를 할당합니까? CLR이 어떤 종류의 최적화 (예 : IEnumerator 개체의 스택 할당)를 수행합니까? 아니면 이것만으로도 충분히 걱정할만한 문제가 아닌가?C에서 이터레이터의 메모리 사용량

답변

13

대부분의 경우 걱정할 정도로 중요하지 않습니다. 에릭이 지적했듯이, 일부는 사례가 중요 할 수 있지만, 실제로는 거의 경험하지 못했습니다.

당신이 foreach 루프 수십만을하고 있다면

는, 아마도 당신은 그 루프 내에서 실제 을하고 있습니다. 거의 확실하게 far 이터레이터보다 더 중요합니다.

foreach을 배열 (컴파일 타임에 배열로 알려져 있음)로 사용하면 IEnumerable<T>이 사용되지 않는다는 점에 유의하십시오. 직접 인덱싱을 사용합니다. 이 코드를 기반으로 코드를 변경하지는 않겠습니다.

성능에 대해 우려하는 경우 이전과 마찬가지로이를 측정하고 프로파일 링해야합니다. 병목 현상은 예상 한 곳이 거의 없습니다.

+13

언제나 그렇듯이 훌륭한 조언 Jon, 우리의 성능 테스트는 일부 실제 시나리오에서 반복기의 힙 할당/가비지 수집에서 중요한 성능 영향을 보여줍니다. 그래서 List 의 열거자는 참조 유형이 아닌 변경 가능한 값 유형입니다. 물론 "성능 테스트"라는 핵심 문구가 있습니다. 데이터없이 성능 결정을 내리는 것은 어리석은 일입니다. –

+2

아 그래, 악의적 인'List '반복자 - 적절한 코드 조각처럼 보이는 뉴스 그룹 포스트를 기억하는 것 같지만 정확히 그 디자인 결정 때문에 매우 이상한 결과를 주었다. 나는 대답을 편집 할 것이다. 어쨌든 ... "중요한 것은 아니다"라는 포괄적 인 주장은 거의 좋은 생각이 아닙니다. –

2

종종 컴파일러는 foreach 루프를 스택 (또는 프로세서 레지스터)에 인덱스 변수 만 필요로하는 간단한 루프로 최적화 할 수 있습니다.

여전히 반복기를 사용하는 경우 대부분 구조체이므로 힙 대신 스택에 할당됩니다.

클래스 인 반복자는 여전히 작고 빠릅니다. 눈에 띄는 영향없이 수백만 개를 만들 수 있습니다.

+0

좋은 소리 ... 빠른 후속 질문 : IEnumerable 인터페이스를 구현하면 정의에 따라 GetEnumerator 메서드가 IEnumerator를 반환합니다. 내 사용자 정의 iterator가 struct 인 경우 boxed 객체로 반환 될 것이라고 가정합니다. –

+6

Jen, _carefully_ List 이 어떻게 작동하는지 살펴보고 복싱을 피하는 방법을 알아 봅니다. 트릭은 * "foreach"루프는 실제로 GetEnumerator가 IEnumerator *를 반환하도록 요구하지 않는다는 것입니다. 올바른 속성과 메서드를 가진 무언가를 반환하는 한, 당신은 황금색입니다. 따라서 구조체를 반환하는 공용 GetEnumerator 및 boxed 구조체를 반환하는 명시적인 IEnumerable .GetEnumerator를 사용하여 복싱을 피할 수 있습니다. –

+4

그러나 Jon이 말했듯이, 힙에 열거자를 만드는 것이 실제적이고 고객에게 영향을 미치는 성능 문제의 주요 원인이라는 확실한 데이터가 없다면이 바보 같은 일을하지 마십시오. 가변 값 유형은 디버깅에 많은 비용이 들고 이해하기 어려운 모든 종류의 이상한 문제를 일으 킵니다. –