를 사용할 때 ToList()
고려해야 할 성능 영향이 있습니까?
디렉토리에서 파일을 검색하는 쿼리를 작성했습니다. 이는 쿼리입니다.
string[] imageArray = Directory.GetFiles(directory);
그러나 List<>
대신 작업을 좋아하기 때문에 …
List<string> imageList = Directory.GetFiles(directory).ToList();
따라서 이와 같은 변환을 결정할 때 고려해야 할 일종의 성능 영향이 있습니까? 아니면 많은 파일을 처리 할 때만 고려해야합니까? 무시할만한 전환입니까?
답변
IEnumerable.ToList()
예, IEnumerable<T>.ToList()
성능에 영향을 미치지 만 성능에 중요한 작업에만주의를 기울여야 하는 O (n) 작업입니다.
ToList()
작업은 사용 List(IEnumerable<T> collection)
생성자를. 이 생성자는 배열의 사본을 만들어야합니다 (보다 일반적으로 IEnumerable<T>
). 그렇지 않으면 원본 배열의 향후 수정 사항 T[]
도 소스에서 변경되어 일반적으로 바람직하지 않습니다.
나는 이것을 거대한 목록으로 만 변화시킬 것이라고 반복하고 싶습니다. 메모리 덩어리를 복사하는 것은 매우 빠른 작업입니다.
편리한 팁 As
vsTo
LINQ에는 As
(와 같은 AsEnumerable()
) 및 To
(과 같은 ToList()
) 로 시작하는 몇 가지 방법이 있습니다. 로 시작하는 메소드는 To
위와 같이 변환 이 필요하며 (즉, 성능에 영향을 줄 수 있음),로 시작하는 메소드는 As
캐스트 또는 간단한 조작이 필요하지 않습니다.
추가 정보 List<T>
List<T>
관심있는 경우 어떻게 작동 하는지에 대한 자세한 내용은 다음과 같습니다. 🙂
A는 List<T>
또한 필요에 따라 크기를 조정해야하는 동적 배열라는 구조를 사용하여,이 크기 조정 이벤트 복사 새로운 배열로 기존 배열의 내용. 따라서 작은 크기로 시작하여 필요한 경우 크기가 늘어납니다 .
의 Capacity
및 Count
속성 의 차이점 입니다 List<T>
. Capacity
장면 뒤의 배열 크기를 나타내며, Count
항목 수 List<T>
는 항상 <= Capacity
입니다. 따라서 항목을 목록에 추가하고을 지나서 늘리면 Capacity
의 크기 List<T>
가 두 배가되고 배열이 복사됩니다.
답변
toList ()를 호출 할 때 성능에 영향이 있습니까?
네 물론 이죠 이론적으로 i++
는 성능에 영향을 미치므로 몇 번의 틱으로 인해 프로그램 속도가 느려집니다.
무엇을 .ToList
합니까?
당신이 호출 할 때 .ToList
, 코드 Enumerable.ToList()
는 확장 메소드 인 호출 을한다 return new List<TSource>(source)
. 해당 생성자 에서 최악의 상황 에서 항목 컨테이너를 통해 하나씩 새 컨테이너에 추가합니다. 따라서 그 동작은 성능에 거의 영향을 미치지 않습니다. 응용 프로그램의 성능 병목이되는 것은 불가능합니다.
질문의 코드에 어떤 문제가 있습니까?
Directory.GetFiles
폴더를 통해 모든 파일의 이름을 즉시 메모리에 반환 하면 string []에 많은 메모리가 소비되어 모든 것이 느려질 수 있습니다.
그때해야 할 일
때에 따라 다르지. 비즈니스 로직뿐만 아니라 폴더의 파일 크기가 항상 작다는 것을 보증하면 코드를 사용할 수 있습니다. 그러나 여전히 Directory.EnumerateFiles
C # 4에서 게으른 버전을 사용하는 것이 좋습니다 . 이것은 쿼리와 훨씬 유사하며 즉시 실행되지 않으며 다음과 같이 쿼리를 더 추가 할 수 있습니다.
Directory.EnumerateFiles(myPath).Any(s => s.Contains("myfile"))
이름에 “myfile”이 포함 된 파일을 찾으면 경로 검색 이 중지 됩니다. 이것은 분명히 더 나은 성능을 가지고 .GetFiles
있습니다.
답변
toList ()를 호출 할 때 성능에 영향이 있습니까?
그렇습니다. 확장 메소드를 사용하면 소스 콜렉션 에서 Enumerable.ToList()
새 List<T>
오브젝트를 구성 IEnumerable<T>
하고 성능에 영향을줍니다.
그러나 이해 List<T>
하면 성능에 미치는 영향이 큰지 판단하는 데 도움이 될 수 있습니다.
List<T>
배열 ( T[]
)을 사용하여 목록의 요소를 저장합니다. 배열은 할당 된 후에는 확장 할 수 없으므로 너무 List<T>
큰 배열을 사용하여 목록의 요소를 저장합니다. (가) 때 List<T>
크기 이상으로 기본 배열을 성장하는 새로운 배열을 할당해야하고 이전 배열의 내용은 목록이 성장하기 전에 새로운 큰 배열에 복사 할 수 있습니다.
새로운 List<T>
것이 만들어 지면 IEnumerable<T>
두 가지 경우가 있습니다.
-
소스 컬렉션 은
ICollection<T>
다음을 구현합니다 . 그런 다음 소스 컬렉션ICollection<T>.Count
의 정확한 크기를 가져 오는 데 사용되고 소스 컬렉션의 모든 요소가를 사용하여 백업 배열에 복사되기 전에 일치하는 백업 배열이 할당됩니다ICollection<T>.CopyTo()
. 이 작업은 매우 효율적이며 메모리 블록 복사를위한 일부 CPU 명령에 매핑 될 수 있습니다. 그러나 성능면에서 새 어레이에는 메모리가 필요하고 모든 요소를 복사하려면 CPU주기가 필요합니다. -
그렇지 않으면 소스 콜렉션의 크기를 알 수 없으며 열거
IEnumerable<T>
자는 각 소스 요소를 새 소스에 한 번에 하나씩 추가하는 데 사용됩니다List<T>
. 처음에 백업 배열이 비어 있고 크기가 4 인 배열이 만들어집니다. 그런 다음이 배열이 너무 작 으면 크기가 두 배가되므로 4, 8, 16, 32 등과 같이 백업 배열이 커집니다. 백업 배열이 커질 때마다 다시 할당해야하고 지금까지 저장된 모든 요소를 복사해야합니다. 이 작업은 정확한 크기의 배열을 즉시 만들 수있는 첫 번째 경우와 비교하여 훨씬 비용이 많이 듭니다.또한 소스 컬렉션에 33 개의 요소가 포함되어 있으면 메모리를 낭비하는 64 개의 요소 배열이 목록에 표시됩니다.
귀하의 경우 소스 컬렉션은 구현하는 배열 ICollection<T>
이므로 소스 배열이 너무 크지 않으면 성능에 영향을 미치지 않습니다. 호출 ToList()
하면 단순히 소스 배열을 복사하여 List<T>
객체로 래핑 합니다. 두 번째 경우의 성능조차도 작은 컬렉션에 대해 걱정할 것이 아닙니다.
답변
“고려해야 할 성능 영향이 있습니까?”
정확한 시나리오의 문제는 무엇보다도 성능에 대한 실제 관심사가 드라이브 캐시의 하드 드라이브 속도와 효율성에 있다는 것입니다.
이러한 관점에서 볼 때 NO는 고려할 필요가 없다는 점에서 그 영향을 무시할 수 있습니다.
그러나 List<>
생산성을 높이거나 알고리즘을 더 친숙하게 만들거나 다른 이점을 얻기 위해 구조 의 기능이 실제로 필요한 경우에만 해당됩니다 . 그렇지 않으면, 아무 이유없이 의도적으로 중요하지 않은 성능 적중을 추가하는 것입니다. 어떤 경우에는 당연히 그렇게해서는 안됩니다! 🙂
답변
ToList()
새로운 List를 만들고 그 안에 요소를 넣습니다. 이는 관련 비용이 있음을 의미합니다 ToList()
. 작은 컬렉션의 경우 비용이 많이 들지 않지만 큰 컬렉션을 보유하면 ToList를 사용할 때 성능이 저하 될 수 있습니다.
콜렉션을 List로 변환하지 않고 수행 할 수없는 작업이 아니면 일반적으로 ToList ()를 사용하지 마십시오. 예를 들어 컬렉션을 반복하려는 경우 ToList를 수행 할 필요가 없습니다.
데이터 소스 (예 : LINQ to SQL을 사용하는 데이터베이스)에 대해 쿼리를 수행하는 경우 지연된 실행을 수행하는 대신 LINQ to SQL과 함께 ToList를 사용할 때 (예 : 필요할 때 항목로드) ToList를 수행하는 비용이 훨씬 더 큽니다. 많은 시나리오에서) 데이터베이스에서 메모리로 항목을 즉시로드합니다.
답변
다음과 같이 비효율적입니다.
var list = new List<T>(items);
를 사용하는 생성자의 소스 코드를 디스 어셈블하면 IEnumerable<T>
몇 가지 작업을 수행 할 수 있습니다.
-
전화는
collection.Count
, 그렇다면collection
이며IEnumerable<T>
, 그것은 실행을 강제 할 것이다. 경우collection
배열리스트 등이며 그되어야O(1)
. -
경우
collection
용구ICollection<T>
, 상기 사용 내부 배열 항목 저장할ICollection<T>.CopyTo
방법. 그것은 해야 할O(n)
것,n
컬렉션의 길이. -
경우
collection
구현하지 않습니다ICollection<T>
, 그것은 컬렉션의 항목을 통해 반복되며, 내부 목록에 추가됩니다.
따라서 새로운 목록을 만들어야하기 때문에 더 많은 메모리를 소비 하며 최악의 경우O(n)
collection
에는 각 요소의 복사본을 만들기 위해 반복됩니다 .
답변
파일 목록 검색 성능을 고려하면 ToList()
무시할 수 있습니다. 그러나 실제로 다른 시나리오에는 해당되지 않습니다. 그것은 실제로 당신이 그것을 사용하는 곳에 달려 있습니다.
-
배열, 목록 또는 다른 컬렉션을 호출 할 때 컬렉션의 복사본을로 만듭니다
List<T>
. 여기에서의 성능은 목록의 크기에 따라 다릅니다. 정말로 필요할 때해야합니다.귀하의 예에서는 배열에서 호출합니다. 배열을 반복하고 항목을 하나씩 새로 만든 목록에 추가합니다. 따라서 성능 영향은 파일 수에 따라 다릅니다.
-
를 호출 하면 (보통 쿼리)
IEnumerable<T>
를 구체화 합니다IEnumerable<T>
.