2017-05-19 14 views
0

私はAWS CPP SDK(https://github.com/aws/aws-iot-device-sdk-cpp)を使用して、小さなLinuxシステム(32 MB RAMのみ)のS3からファイルをダウンロードしています。私は以下のようにGetObjectRequestクラスを使用していました。それは素晴らしい仕事をし、私のシステム上でFStreamにファイルをダウンロードしたので、あまりにも多くのRAMを消費しませんでした。AWS CPP TransferManagerとGetObjectRequestストリームをファイルfstream OOM

進捗コールバックを取得するために、ダウンロードコードをTransferManagerメソッドに変換したいと思います。私はコードのその部分を書き直しました、そして、それは同様に以下に示されています。それはうまく始まり、ダウンロードされたパーセンテージを出力しますが、14 MBのRAM(ダウンロード時にLinuxで利用可能な量)に達すると、あまりにも多くのRAMを使用するためにカーネルによって殺されます。

私はGetObjectRequestの場合と同じようにファイルストリームを作成しました。私は間違って何をしていますか?これをどうすれば解決できますか?ありがとう。最終的にあまりにも多くのRAMを使用し、カーネルによって殺され

// Old way 
    GetObjectRequest getObjectRequest; 
    getObjectRequest.SetBucket(bucket.c_str()); 
    getObjectRequest.SetKey(keyName.c_str()); 
    getObjectRequest.SetResponseStreamFactory([&destination](){ 
    return Aws::New<Aws::FStream>(
    "s3file", destination, std::ios_base::out); }); 

    GetObjectOutcome getObjectOutcome = SessionClient->GetObject(getObjectRequest); 
    if(getObjectOutcome.IsSuccess()) 
    { 
     std::cout << "<AWS DOWNLOAD> Get FW success!" << std::endl; 
    } 
    else 
    { 
     std::cout << "<AWS DOWNLOAD> Get FW failed: " << getObjectOutcome.GetError().GetMessage() << std::endl; 
     exit(1); 
    } 

新しい方法:

// New way 
Aws::Transfer::TransferManagerConfiguration transferConfig; 
transferConfig.s3Client = SessionClient; 

std::shared_ptr<Aws::Transfer::TransferHandle> requestPtr(nullptr); 

transferConfig.downloadProgressCallback = 
     [](const Aws::Transfer::TransferManager*, const Aws::Transfer::TransferHandle& handle) 
{ 
    std::cout << "\r" << "<AWS DOWNLOAD> Download Progress: " << static_cast<int>(handle.GetBytesTransferred() * 100.0/handle.GetBytesTotalSize()) << " Percent " << handle.GetBytesTransferred() << " bytes\n"; 
}; 

Aws::Transfer::TransferManager transferManager(transferConfig); 

requestPtr = transferManager.DownloadFile(bucket.c_str(), keyName.c_str(), [&destination](){ 

    Aws::FStream *stream = Aws::New<Aws::FStream>("s3file", destination, std::ios_base::out); 
    stream->rdbuf()->pubsetbuf(NULL, 0); 

    return stream; }); 

requestPtr->WaitUntilFinished(); 

size_t retries = 0; 
//just make sure we don't fail because a download part failed. (e.g. network problems or interuptions) 
while (requestPtr->GetStatus() == Aws::Transfer::TransferStatus::FAILED && retries++ < 5) 
{ 
    std::cout << "<AWS DOWNLOAD> FW Download trying download again!" << std::endl; 
    transferManager.RetryDownload(requestPtr); 
    requestPtr->WaitUntilFinished(); 
} 

// Check status 
if (requestPtr->GetStatus() == Aws::Transfer::TransferStatus::COMPLETED) { 
    if (requestPtr->GetBytesTotalSize() == requestPtr->GetBytesTransferred()) { 
     std::cout << "<AWS DOWNLOAD> Get FW success!" << std::endl; 
     exit(0); 
    } 
    else { 
     std::cout << "<AWS DOWNLOAD> Get FW failed - Bytes downloaded did not equal requested number of bytes: " << requestPtr->GetBytesTotalSize() << requestPtr->GetBytesTransferred() << std::endl; 
     exit(1); 
    } 
} 
else { 
    std::cout << "<AWS DOWNLOAD> Get FW failed - download was never completed even after retries" << std::endl; 
    exit(1); 
} 

答えて

1

TransferManagerは本当に簡単に一度のものを作るすべてのRAMを使用していませんでした

古い方法あなたは10MB以上の土地にいて、並列化を利用したいと思っています。最大のヒープサイズを前面に割り当て、ヒープをそれより大きくすることはありません。あなたのRAMの制約を考えると、私はTransferManagerを使用しません。進行通知を引き続き受け取ることができます。 AmazonWebServiceRequestクラスのコールバックメカニズムを確認してください。

関連する問題