2011-02-01 3 views
15

업데이트 : 예상 했어야 할 것처럼이 질문에 대한 커뮤니티의 건전한 조언은 "측정하여보고"하는 것이 었습니다. chibacity posted an answer 나를 위해 이렇게 좋은 테스트가 있습니다. 한편, 나는 내 자신의 시험을 썼다. 내가 본 성능 차이는 실제로 I felt compelled to write a blog post about it.ThreadStatic을 사용하여 값 비싼 지역을 대체하는 것이 좋습니다.

그러나, 나는 또한 ThreadStatic 속성이 참으로 무료로하지 않습니다 실제로 마법을 작동하기 위해 CLR 도우미 방법에 의존하는 Hans's explanation을 인정해야 너무 거대했다. 이것은 임의의 경우에 적용하는 것이 적절한 최적화인지 여부를 명확히하지 않습니다.

내게 좋은 소식은 경우에 큰 개선을 한 것으로 보입니다.


나는 (많은 다른 것들 사이에) 몇 지역 변수에 대한 몇 가지 중간 크기의 배열 (~ 50 요소)를 인스턴스화하는 방법이있다.

필자는이 방법을 성능 병목 현상으로 확인했습니다. 이 방법이 전화하는 데 오랜 시간이 걸리는 것은 아닙니다. 오히려 간단히 번, 매우 신속하게 (몇 시간이 될 수있는 세션에서 수십만에서 수백만 번) 호출됩니다. 따라서 상대적으로 작은 성능 개선만으로도 가치가 있어야합니다.

각 호출마다 새 배열을 할당하는 대신 [ThreadStatic]으로 표시된 필드를 사용할 수있었습니다. 메소드가 호출 될 때마다 현재 스레드에서 필드가 초기화되었는지 확인하고 그렇지 않으면 초기화합니다. 그 시점에서 같은 스레드에 대한 모든 호출에 그 시점에 갈 준비가 된 배열이 생깁니다. 이것은 좋은 생각 같지 않습니다

내 질문은 단순히 이것이다. (이 방법은 배열 자체의 모든 요소를, 그래서 문제가되지해야 배열의 "오래된"요소를 갖는 초기화)? 이런 방식으로 ThreadStatic 속성을 사용하는 데있어주의해야 할 사항 (즉, 로컬 변수에 대한 새 객체를 인스턴스화하는 비용을 줄이기위한 성능 최적화)에 대해 알아야 할 사항이 있습니까? ThreadStatic 필드 자체의 성능이 좋지 않을 수도 있습니다. 예를 들어,이 기능을 사용 가능하게 만들기 위해 백그라운드에서 비용이 많이 드는 추가 "물건"이 많이 있습니까? 그 때문에 만약

그것은 심지어 50 요소로 싼 뭔가 (?) 최적화하기 위해 시도 할 틀렸다 나에게도 꽤 그럴듯의 배열을-하고, 확실히 알려-하지만하자 일반 질문 여전히 보유.

+1

시도해보십시오. thread-local 항목에 액세스하는 것은 무료가 아니지만 재 할당보다 비용이 적게 듭니다. – 9000

+0

시도해보고 측정하십시오. – BRampersad

+0

.NET4를 사용할 수 있다면 ['ThreadLocal '] (http://msdn.microsoft.com/en-us/library/dd642243.aspx)도 잊지 마십시오. 배심원 단은 여전히'ThreadStatic'보다 성능이 좋았는지에 관해서는 나왔지만 사용하기가 쉽습니다. 'ThreadLocal '을 고려하여 벤치 마크에 포함시키는 것이 좋습니다. – LukeH

답변

5

간단한 벤치 마크를 수행했으며 ThreadStatic은 질문에 설명 된 간단한 매개 변수에 대해 더 나은 성능을 보입니다.

는 반복의 높은 번호가 많은 알고리즘과 마찬가지로, 나는 그것이 새로운 배열을 할당하는 버전을 죽이는 GC 오버 헤드의 간단한 경우를 의심 : 테스트를

업데이트

을 그

Iterations : 10,000,000 

Local ArrayRef   (- array iteration) : 330.17ms 
Local ArrayRef   (- array iteration) : 327.03ms 
Local ArrayRef   (- array iteration) : 1382.86ms 
Local ArrayRef   (- array iteration) : 1425.45ms 
Local ArrayRef   (- array iteration) : 1434.22ms 
TS CopyArrayRefLocal (- array iteration) : 107.64ms 
TS CopyArrayRefLocal (- array iteration) : 92.17ms 
TS CopyArrayRefLocal (- array iteration) : 92.42ms 
TS CopyArrayRefLocal (- array iteration) : 92.07ms 
TS CopyArrayRefLocal (- array iteration) : 92.10ms 
Local ArrayRef   (+ array iteration) : 1740.51ms 
Local ArrayRef   (+ array iteration) : 1647.26ms 
Local ArrayRef   (+ array iteration) : 1639.80ms 
Local ArrayRef   (+ array iteration) : 1639.10ms 
Local ArrayRef   (+ array iteration) : 1646.56ms 
TS CopyArrayRefLocal (+ array iteration) : 368.03ms 
TS CopyArrayRefLocal (+ array iteration) : 367.19ms 
TS CopyArrayRefLocal (+ array iteration) : 367.22ms 
TS CopyArrayRefLocal (+ array iteration) : 368.20ms 
TS CopyArrayRefLocal (+ array iteration) : 367.37ms 
TS TSArrayRef  (+ array iteration) : 360.45ms 
TS TSArrayRef  (+ array iteration) : 359.97ms 
TS TSArrayRef  (+ array iteration) : 360.48ms 
TS TSArrayRef  (+ array iteration) : 360.03ms 
TS TSArrayRef  (+ array iteration) : 359.99ms 
,536 : 최소 배열 참조 사용 모델 플러스 기준 로컬 복사 된 이전 테스트 이외에 ThreadStatic 배열 참조 사용하는 어레이의 추가 반복을 포함

코드 :

+0

현실적인 비교를 위해 배열을 사용하는 것이 좋을 것입니다. –

+0

@ 500 좋은 지적 -하지만 특정 문제를 볼 수 있습니까? –

+0

필자는 [ThreadStatic]을 아직 사용하지 않았기 때문에 전문적 지식이 없지만 관리되지 않는 코드에 해당하는 것은 모든 액세스에 오버 헤드가 있습니다. 아마 여기에 사용하기 전에 [ThreadStatic]을 로컬에 복사하여 완화 할 수 있지만, 일부 숫자를 보는 것은 흥미로울 것입니다. –

2

this과 같은 결과에서 ThreadStatic은 매우 빠르게 보입니다. 50 개 요소 배열을 더 빨리 재 할당하면 누구에게나 확실한 답을 줄지 확신 할 수 없습니다. 그것은 당신이 벤치마킹해야 할 일입니다. :)

나는 그것이 "좋은 생각"인지 아닌지에 대해서는 다소 찢겨져 있습니다. 모든 구현 세부 사항이 클래스 내부에 유지되는 한 나쁜 생각은 아닙니다 (실제로 호출자가 걱정하지 않아도되기를 바라지는 않습니다). 벤치 마크가이 방법으로 성능 향상을 나타내지 않으면 간단하게 코드를 더 간단하고 읽기 쉽게 만들어주기 때문에 매번 배열을 할당해야합니다. 두 가지 솔루션 중 더 복잡한 것이기 때문에이 옵션을 선택하기 전에 복잡성의 이점을 확인해야합니다.

8

[ThreadStatic]은 아니요 무료 점심입니다. 변수에 대한 모든 액세스는 지터로 인라인 컴파일되지 않고 CLR (JIT_GetThreadFieldAddr_Primitive/Objref)의 도우미 함수를 거쳐야합니다. 또한 지역 변수를 대체 할 수있는 것이 아니라 재귀가 바이트로 처리됩니다. 루프에서 많은 CLR 코드로 성능을 예측할 수 없습니다.

+1

함수 호출 당 한 번만 비용을 지불하면됩니다 (배열에 대한 참조를 가져 와서 실제 지역에 저장하기 위해) – Yuliy

+0

아니요, 무료 점심도 아닙니다. 객체 참조는 여전히 스텁을 통과합니다. –

관련 문제