2008-09-18 8 views
15

내가 여기서 작업하는 시스템은 .net 2.0 이전에 작성되었으며 제네릭의 이점이 없었습니다. 결국 2.0으로 업데이트되었지만 시간 제한으로 인해 코드가 리팩토링되지 않았습니다. 코드가 객체를 객체로 저장하는 ArraysLists 등을 사용하는 곳이 많이 있습니다.Generics 대 Array List

성능 관점에서 코드를 generics 사용으로 변경하는 것이 얼마나 중요합니까? 나는 perfomance 관점, 복싱 및 unboxing 등에서, 그것은 비효율적이지만 성능 향상의 얼마나 많은 변화가 실제로있을 것입니다 알아? 제네릭은 앞으로 나아갈 방향으로 사용할 것이 있습니까? 아니면 이전 코드를 업데이트하기 위해 양심적 노력을 기울여야 할 충분한 성능 변화가 있습니까?

답변

14

기술적으로 제네릭의 성능은 당신이 말한대로 더 좋습니다. 그러나 성능이 매우 중요하지 않고 다른 분야에서 이미 최적화 된 경우가 아니면 다른 곳에서 시간을 보내고 더 나은 개선 효과를 얻을 수 있습니다.

내가 제안 :

  • 사용 제네릭 앞으로.
  • 당신은 당신이
  • 다른 시간이 크게 (등 데이터베이스 호출, 변화하는 데이터 구조) 성능이 향상됩니다/측정 리팩토링을 수행을 보내고 코드를 만지지로 고체 단위 테스트를 한 후 여기 저기 오히려 몇 밀리 초보다 제네릭에 리팩토링이있는 경우 . 물론

는 제네릭으로 변경하는 성능보다 다른 이유가있다 :

  • 적은 오류가 발생하기 쉬운, 당신은 컴파일 시간을
  • 더 읽기 유형의 확인이 있기 때문에, 당신은 캐스팅 할 필요가 없습니다 사방과 모음에 저장되어있는 어떤 종류의 그것은 분명
  • 당신이 그때는
4

확실히 알 수있는 유일한 방법은 dotTrace와 같은 도구를 사용하여 코드를 프로파일하는 것입니다.

http://www.jetbrains.com/profiler/

그것은 권투/언 박싱은 특정 응용 프로그램에서 사소한 및 리팩토링 가치가 없을 것이 가능하다. 앞으로 컴파일 시간 형식 안전성 때문에 제네릭 사용을 고려해야합니다.

0

가장 큰 이익은 유지 관리 단계에서 찾을 수 있습니다. Generics는 변환 및 캐스팅 문제를 처리하지 않고도 다루기 쉽고 업데이트하기가 훨씬 쉽습니다. 이것이 계속 방문하는 코드라면 꼭 모든 노력을 기울이십시오. 이것이 수년 만에 다루어지지 않은 코드라면,별로 신경 쓰지 않을 것입니다.

1

달려있다. 가장 좋은 대답은 코드를 프로파일 링하고 보는 것이다. 나는 AQTime을 좋아하지만 이것을 위해 많은 패키지가 존재한다.

일반적으로 ArrayList를 많이 사용하는 경우 일반 버전으로 전환 할 가치가 있습니다. 실제로는 성능 차이를 측정 할 수 없을 수도 있습니다. 복싱과 언 박싱은 추가 단계이지만 현대 컴퓨터는 너무 빠르기 때문에 거의 차이가 없습니다. ArrayList는 멋진 랩퍼가있는 정상적인 배열이므로 generics로 변환하는 것보다 더 나은 데이터 구조 선택 (ArrayList.Remove는 O (n)입니다!)에서 얻은 성능이 훨씬 향상 될 것입니다.

편집 : Outlaw 프로그래머가 좋은 지적을 가지고 있으며, 당신은 여전히 ​​복싱 및 제네릭과 함께 unboxing 것입니다, 그것은 단지 암시 적으로 발생합니다. 캐스팅과 "is/as"키워드에서 예외 및 null을 확인하는 데 필요한 모든 코드는 약간 도움이됩니다.

0

autoboxing/unboxing은 generics와 무슨 관련이 있습니까? 이는 형식 안전 문제 일뿐입니다. 비 제네릭 컬렉션을 사용하면 명시 적으로 객체의 실제 유형으로 다시 캐스트해야합니다. 제네릭을 사용하면이 단계를 건너 뛸 수 있습니다. 나는 성능 차이가 있다고 생각하지 않는다.

+2

구조체를 사용할 때 제네릭과 그 유용성에 대한 문서를 살펴보면 어떤 복싱이 구조체와 관련되는지 알 수 있습니다. (힌트 : 스택 변수에 객체 포인터를 가져올 수 없음) – Guvante

0

내 회사에서 실제로이 문제를 고려했습니다. 우리가 취한 접근 방식은 다음과 같습니다. 리팩토링하는 것이 쉬운 경우 수행하십시오. 그렇지 않은 경우 (즉, 너무 많은 클래스를 건드릴 것임), 나중에 두십시오. 실제로 할 시간이 있는지 또는 코딩 할 항목이 더 중요한지 (예 : 고객을 위해 구현해야하는 기능)에 달려 있습니다.

그런데 다시 클라이언트를 위해 작업하지 않으면 리팩토링에 시간을 할애해야합니다. 코드의 가독성이 향상됩니다.

3

Java 또는 .NET과 상관없이 Generics는 성능이 아닌 디자인 및 유형 안전성에 사용해야합니다. Autoboxing은 제네릭과 다릅니다 (본질적으로 암시 적 객체에서 원시적 변환으로). 앞서 언급 한 것처럼 산술 연산이나 반복 연산으로 인해 성능에 영향을 줄 수있는 다른 연산이있을 경우 기본 연산 대신 사용해서는 안됩니다. 암시 적 객체 생성/파괴.

전반적으로 성능 향상이 아닌 유형 안전/디자인 용도로 정리해야하는 경우 기존 코드 만 업데이트하는 것이 좋습니다.

0
사방을 사용하는 청소기의 향후 제네릭을 사용하는 경우

코드에 얼마만큼 밖에 있는지에 달려 있습니다. UI에 큰 목록을 바인딩하거나 표시하면 성능이 크게 향상됩니다.

ArrayList가 여기저기서 뿌리 째 꽂히는 경우 정리하기가별로 쉽지 않을뿐 아니라 전반적인 성능에 큰 영향을 미치지 않을 것입니다.

코드 전반에 걸쳐 많은 ArrayLists를 사용하고 있고이를 대체하기가 어렵다면 (일정에 영향을 줄 수있는 무언가), if-you-touch-it-change-it 접근.

하지만 Generics는 읽기 쉽고 강력한 타자를 치기 때문에 앱 전체에서 안정적입니다. 성능뿐만 아니라 코드의 유지 보수성과 안정성을 통해 이익을 얻을 수 있습니다. 네가 빨리 그것을 할 수 있다면, 나는 그렇게 말할 것이다.

제품 소유자로부터 바이 인을받을 수 있다면 정리 해둘 것을 권합니다. 나중에 코드를 더 좋아합니다.

0

ArrayLists의 엔터티가 Object 유형 인 경우 올바른 유형으로 캐스팅하지 않으면 약간의 이점을 얻을 수 있습니다. 값 유형 (Int32와 같은 구조체 또는 프리미티브) 인 경우 boxing/unboxing 프로세스는 많은 오버 헤드를 추가하고 Generic 컬렉션은 훨씬 빨라야합니다.

Here's an MSDN article on the subject

8

여기에 내가 1백킬로바이트 파일에서 문자열을 10 만 시간의 간단한 분석에서 얻은 결과입니다. 일반 목록 (Of Char)은 파일을 통해 10,000 번 이동하는 데 612.293 초가 걸렸습니다. ArrayList는 파일을 통해 100,000 번 이동하는 데 2,880.415 초가 걸립니다. 즉,이 시나리오에서 (마일이 일 때이 변함) 일반 목록 (문자 중)이 4.7 배 빠릅니다.당신이 얻을 수 있습니다 어디 가치 유형 (INT, BOOL, 구조체 등)를 사용하게 될 경우

Public Sub Run(ByVal strToProcess As String) Implements IPerfStub.Run 
    Dim genList As New ArrayList 

    For Each ch As Char In strToProcess.ToCharArray 
     genList.Add(ch) 
    Next 

    Dim dummy As New System.Text.StringBuilder() 
    For i As Integer = 0 To genList.Count - 1 
     dummy.Append(genList(i)) 
    Next 

End Sub 

Public Sub Run(ByVal strToProcess As String) Implements IPerfStub.Run 
    Dim genList As New List(Of Char) 

    For Each ch As Char In strToProcess.ToCharArray 
     genList.Add(ch) 
    Next 

    Dim dummy As New System.Text.StringBuilder() 
    For i As Integer = 0 To genList.Count - 1 
     dummy.Append(genList(i)) 
    Next 
End Sub 
0

제네릭이 특히 더 나은 성능을 가지고 : 여기

내가 10 시간을 통해 실행 된 코드입니다 눈에 띄는 성능 향상. 가치 유형

  1. 사용 ArrayList를 수백 번하는 경우에 일반적인 목록을 사용하여 다음 substantialy 느린 복싱/언 박싱됩니다.

  2. 값 유형을 객체로 저장할 때 항목 당 최대 4 회의 시간 메모리가 사용됩니다. 이 양은 RAM을 소모하지 않지만 더 작은 캐시 메모리는 더 적은 항목을 포함 할 수 있습니다. 즉, 긴 콜렉션을 반복하는 동안 주 메모리에서 캐시로 응용 프로그램을 느리게하는 많은 사본이 있음을 의미합니다.

here이라고 썼습니다.

+1

애플리케이션 로직에 결함이 있습니다. 특히 InsertItemsToList에는 stopper.Start()가 잘못 배치되어 있습니다. 루프 내부에 있어야합니다. 또한 객체의 List <>와 객체의 ArrayList를 사용할 때 성능 차이는 최소화됩니다. 즉, 약 10 %의 속도 향상 (내 번호는 1.982/1.81/1.233/1.089)입니다. 물론, List <>와 ArrayList의 성능 향상은 int에서 매우 명백합니다. 클래스에는없는 것입니다. – JustLoren

+0

@ JustLoren - 사소한 "오류"가 없어도 계산은 거의 같습니다. 그리고 나는 나의 대답 (위)과 블로그 게시물에서 둘 다 썼다. 왜냐하면 가치 차이는 주로 가치 유형의 복싱/언 박싱 때문이다. –

0

제네릭을 사용하면 이후의 C# 버전에서 linq와 같은 것을 활용하려는 경우 코드가 더 간단하고 사용하기 쉬워졌습니다.