2

한 원본에서 다른 원본으로 복사 할 개체 목록이 있습니다. It was suggested that I could speed things up을 사용하여 Parallel.ForEach이 ForEach (..) 코드에서 Parallel.ForEach (..)를 사용하여 리팩터링 할 수 있습니까?

Parallel.ForEach(..)을 활용하려면 다음 pseduo 코드를 어떻게 리팩터링 할 수 있습니까?

var foos = GetFoos().ToList(); 
foreach(var foo in foos) 
{ 
    CopyObjectFromOldBucketToNewBucket(foo, oldBucket, newBucket, 
     accessKeyId, secretAccessKey); 
} 

CopyObjectFromOldBucketToNewBucket

다른 한 양동이에서 항목을 이동 아마존 REST API를 이용한다.

건배 :)

답변

3

Parallel은 실제로는 최선의 옵션이 아닙니다. Parallel은 코드를 병렬로 실행하지만 AWS에 대한 각 요청에 대해 여전히 스레드 풀 스레드를 사용합니다. 대신 BeginCopyObject 메서드를 사용하는 것이 리소스를 훨씬 효율적으로 사용할 수 있습니다. 이것은 응답 대기중인 스레드 풀 스레드를 사용하지 않지만 응답을 받았을 때 처리 할 필요가있을 때만 스레드 풀 스레드를 사용합니다.

다음은 시작/종료 방법을 사용하는 방법에 대한 간단한 예입니다. 이것들은 AWS에만 국한되는 것이 아니라 .NET BCL 전체에서 발견되는 패턴입니다.

public static CopyFoos() 
{ 
    var client = new AmazonS3Client(...); 
    var foos = GetFoos().ToList(); 
    var asyncs = new List<IAsyncResult>(); 
    foreach(var foo in foos) 
    { 
     var request = new CopyObjectRequest { ... }; 

     asyncs.Add(client.BeginCopyObject(request, EndCopy, client)); 
    } 

    foreach(IAsyncResult ar in asyncs) 
    { 
     if (!ar.IsCompleted) 
     { 
      ar.AsyncWaitHandle.WaitOne(); 
     } 
    } 
} 

private static EndCopy(IAsyncRequest ar) 
{  
    ((AmazonS3Client)ar.AsyncState).EndCopyObject(ar); 
} 

생산 코드의 경우 발송 한 요청 수를 추적하고 한 번에 제한된 숫자 만 발송할 수 있습니다. 테스트 또는 AWS 문서는 최적의 동시 요청 수를 알려줍니다.

이 경우 우리는 실제로 요청이 완료 될 때 아무 것도 할 필요가 없으므로 EndCopy 호출을 건너 뛰고 싶지만 리소스가 누출 될 수 있습니다. BeginXxx를 호출 할 때마다 해당 EndXxx 메서드를 호출해야합니다.

+0

'BeginCopyObject'에 대한 더 많은 정보를 제공해 주실 수 있습니까? –

+0

@ Pure.Krome, 중요한 정보가 담긴 샘플을 추가했습니다. –

3

는 코드가 foos보다 다른 종속성을 가지고 있지 않기 때문에 당신은 간단하게 수행 할 수 있습니다

Parallel.ForEach(foos, (foo => 
{ 
    CopyObjectFromOldBucketToNewBucket(foo, oldBucket, newBucket, 
             accessKeyId, secretAccessKey); 
})); 

가 I을하지만 명심/O 만에 병렬화 될 수있다 그 정도의 성능은 실제로 저하 될 수 있습니다.

+1

이러한 작업이 I/O 의존적이며 장기간 실행되는 경우 최상의 방법이 아닐 수 있습니다. –

관련 문제