AWS S3にアップロードする130以上のアイテムを反復処理パフォーマンスを向上させる方法

fsakiyama :

私は130以上のデータ転送オブジェクトを反復処理する必要があり、それぞれの時間は、AWS S3にアップロードするためのJSONを生成します。

ノー改善と、それは周りにかかる90秒を全体のプロセスを完了します。私は、ラムダを使用し、ラムダ、両方に同じ結果を使用していないみました。

for(AbstractDTO dto: dtos) {
    try {
        processDTO(dealerCode, yearPeriod, monthPeriod, dto);
    } catch (FileAlreadyExistsInS3Exception e) {
        failedToUploadDTOs.add(e.getLocalizedMessage() + ": " + dto.fileName() + ".json");
    }
}
dtos.stream().forEach(dto -> {
    try {
        processDTO(dealerCode, yearPeriod, monthPeriod, dto);
    } catch (FileAlreadyExistsInS3Exception e) {
        failedToUploadDTOs.add(e.getLocalizedMessage() + ": " + dto.fileName() + ".json");
    }
});

いくつかの調査の後、私はこの方法processDTOが周りに取ると結論づけ0.650ms実行するアイテムごとに。

私の最初の試みは、使用していた並列ストリームを、そしてその結果は周りを取って、かなり良かった15秒全体のプロセスを完了するために:

dtos.parallelStream().forEach(dto -> {
    try {
        processDTO(dealerCode, yearPeriod, monthPeriod, dto);
    } catch (FileAlreadyExistsInS3Exception e) {
        failedToUploadDTOs.add(e.getLocalizedMessage() + ": " + dto.fileName() + ".json");
    }
});

しかし、私はまだその時間を短縮する必要があります。私は、並列ストリームの改善について研究し、発見されたForkJoinPoolのトリックを:

ForkJoinPool forkJoinPool = new ForkJoinPool(PARALLELISM_NUMBER);
forkJoinPool.submit(() ->
dtos.parallelStream().forEach(dto -> {
    try {
        processDTO(dealerCode, yearPeriod, monthPeriod, dto);
    } catch (FileAlreadyExistsInS3Exception e) {
        failedToUploadDTOs.add(e.getLocalizedMessage() + ": " + dto.fileName() + ".json");
    }
})).get();
forkJoinPool.shutdown();

残念ながら、結果は私のために混乱ビットでした。

  • PARALLELISM_NUMBERが8である場合、それは周りにかかる13秒を全体のプロセスを完了すること。ビッグは改善されません。
  • PARALLELISM_NUMBERが16であるとき、それは周りの取り8秒の全体のプロセスを完了すること。
  • PARALLELISM_NUMBERが32である場合、それは周りのかかる5秒の全体のプロセスを完了すること。

すべてのテストは終了アップになる130個の項目を反復コントローラメソッドを呼び出し、郵便配達の要求を用いて行きました

私はPARALLELISM_NUMBERとして32を使用して、5秒に満足していますが、私は結果を心配しています。

  • それは32を維持するために、OKですか?
  • 理想的なのPARALLELISM_NUMBERは何ですか?
  • 私はその価値を決定する際に心に留めておく必要がありますか?

私は、Mac 2.2GHzのI7上で実行していますよ

sysctl hw.physicalcpu hw.logicalcp
hw.physicalcpu: 4
hw.logicalcpu: 8

ここでは何processDTOを行います。

private void processDTO(int dealerCode, int yearPeriod, int monthPeriod, AbstractDTO dto) throws FileAlreadyExistsInS3Exception {
    String flatJson = JsonFlattener.flatten(new JSONObject(dto).toString());
    String jsonFileName = dto.fileName() + JSON_TYPE;;
    String jsonFilePath = buildFilePathNew(dto.endpoint(), dealerCode, yearPeriod, monthPeriod, AWS_S3_JSON_ROOT_FOLDER);
    uploadFileToS3(jsonFilePath + jsonFileName, flatJson);
}
public void uploadFileToS3(String fileName, String fileContent) throws FileAlreadyExistsInS3Exception {
    if (s3client.doesObjectExist(bucketName, fileName)) {
        throw new FileAlreadyExistsInS3Exception(ErrorMessages.FILE_ALREADY_EXISTS_IN_S3.getMessage());
    }
    s3client.putObject(bucketName, fileName, fileContent);
}
fsakiyama :

私はに減らすことに成功し8秒すべてのあなたの役に立つアドバイスや説明のおかげで。

ボトルネックは、AWS S3にアップロードして、あなたがAWSでの非ブロッキングAPIを述べたので、いくつかの研究の後、私はクラスのことが判明TransferManagerが含まれている非ブロックアップロードを。

TransferManagerクラス

だからではなく、スレッドの数を増やすことForkJoinPoolを使用しての、私はシンプルなparallelStreamを保ちました:

        dtos.parallelStream().forEach(dto -> {
            try {
                processDTO(dealerCode, yearPeriod, monthPeriod, dto);
            } catch (FileAlreadyExistsInS3Exception e) {
                failedToUploadDTOs.add(e.getLocalizedMessage() + ": " + dto.fileName() + ".json");
            }
        });

そしてuploadToS3Method代わりに使用するのでは、少しも変わってAmazonS3を、私が使用TransferManagerを

public Upload uploadAsyncFileToS3(String fileName, String fileContent) throws FileAlreadyExistsInS3Exception {
        if (s3client.doesObjectExist(bucketName, fileName)) {
            throw new FileAlreadyExistsInS3Exception(ErrorMessages.FILE_ALREADY_EXISTS_IN_S3.getMessage());
        }
        InputStream targetStream = new ByteArrayInputStream(fileContent.getBytes());
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentLength(fileContent.getBytes().length);
        return transferManager.upload(bucketName, fileName, targetStream, metadata);
}

アップロードが呼び出されたときに、この方法は、それが処理される別のDTOをさせる、最後までそれを待ちません。すべてのDTOが処理されると、私は(最初のforEach外)可能性のあるエラーを確認するために彼らのアップロードステータスを確認します

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=136961&siteId=1