2012-01-22 3 views
0

데이터베이스 쿼리 캐시로 사용되는 사전의 각 문자열 키에 대해 문자열 비교 연산의 성능을 최적화하려고합니다. 나는 C#을 병렬 기능을 사용하여 새로 온 사람과 가장 좋은 방법은 여러 문자열 비교가 '동시에'이 일어날 수 있도록 병렬 운전이 점을 변환하는 것입니다 무엇인지 궁금문자열 비교의 병렬 최적화

public void Clear(string tableName) 
{ 
    foreach (string key in cache.Keys.Where(key => key.IndexOf(tableName, StringComparison.Ordinal) >= 0).ToList()) 
    { 
     cache.Remove(key); 
    } 
} 

: 같은 현재의 코드가 보인다. 캐시는 종종 상당히 커질 수 있으므로 Clear()을 사용하면 유지 관리에 많은 비용이 소요될 수 있습니다.

+3

"캐시가 종종 상당히 커질 수 있습니다"- 성능 병목 현상이 있는지 측정 했습니까? 그렇지 않은 경우 스레드를 도입해도 아무 것도 얻지 못하고 복잡성이 증가합니다. –

+1

내가 처음이라면 코드를 병렬 처리하기보다는 캐싱 접근 방식을 최적화하는 것이 좋습니다. – Lazarus

+0

필자는 성능 분석기를 실행하여이 방법 내에서, 특히 IndexOf() 내에서 샘플의 70 %가 사용되었다고합니다. 불행히도 기존 프레임 워크에서이 캐싱 접근 방식을 사용하도록 제한되어 있습니다. 캐시의 요소 수에 상한선을 부과하고 싶었지만 옵션이 아닙니다. – dahvyd

답변

1

cache 개체를 ConcurrentDictionary으로 만들고 Remove 대신 TryRemove을 사용하십시오.

이렇게하면 캐시가 스레드로부터 안전 해집니다. 다음과 같이 현재 foreach 루프를 호출 할 수 있습니다 : 당신에게 출발점을 제공

Parallel.ForEach(cache.Keys, key => 
{ 
    if(key.IndexOf(tableName, StringComparison.Ordinal) >= 0) 
    { 
     dynamic value; // just because I don't know your dictionary. 
     cache.TryRemove(key, out value); 
    } 
}); 

희망을.

+2

스레딩없이 직렬 제거보다 속도가 느릴 수 있습니다. – SLaks

+0

수 있습니까? – bevacqua

+0

스레드 안전성이 높습니다. – SLaks

1

Dictionary<string, Whatever>에 대한 접근 방식은 여러 작성기에 대해 스레드로부터 안전하지 않으므로 동시 삭제로 인해 모든 종류의 문제가 발생할 수 있습니다.

따라서 잠금을 사용하여 제거를 동기화해야하므로 사전에 기본적으로 단일 스레드 액세스가 이루어집니다. 스레드를 통해 안전하게 수행 할 수있는 유일한 작업은 Where의 비교입니다.

스트라이프 잠금을 사용하면이 영향이 줄어들 수 있기 때문에 ConcurrentDictionary을 사용할 수 있습니다. 그래도 여전히 최선의 접근법으로 보이지 않습니다.

문자열에서 키를 생성하여 키가 하위 키로 시작하는지 테스트하고 전체 하위 키를 자주 제거해야하는 경우 Dictionary<string, Dictionary<string, Whatever>>을 사용해보십시오. 추가 또는 업데이트는 조금 비싸지 만 지우기는 상위 수준 사전에서 하나의 값만 O (1) 제거합니다.

+0

아이디어를 제공해 주셔서 감사합니다.하지만 추가 비용이 들지는 않습니다. – dahvyd

+0

어떤 종류의 추가 오버 헤드가 있습니까? 평행선을 지우려는 생각에 고유 한 오버 헤드가 있습니다. 분할 조회의 오버 헤드는 어디에서 영향을받지 않습니까? –

0

이전에 캐시로 사전을 사용했으며 이전에 캐시를 정리하는 것, 즉 각 항목마다 포함 시간을 포함 시키므로 언제든지 캐시를 정리하는 것입니다. 항목을 요청합니다. 이전 항목을 제거합니다. 성능 적중률은 나에게는 적지 만 필요에 따라이 시간 소인을 보관할 인덱스로 큐 (Tuple<DateTime, TKey>의 경우 TKey이 사전의 키 유형 임)를 구현하여 매번 전체 사전을 반복 할 필요가 없었습니다 . 어쨌든 이러한 문제에 대해 생각할 필요가 없다면 전용 캐싱 서버를 사용할 때입니다. 나에게 공유 캐시 (http://sharedcache.codeplex.com)가 충분했다.

관련 문제