背景
タグについて
AWSはリソースにタグの付与が可能です。AWSにおけるタグはリソースの管理やコスト配分の用途で用いられ、タグの付与設計はAWSの運用において非常に重要なポイントとなります。
特に大規模な環境や組織になるとリソースに付与するタグは非常に多くなる傾向があります。
AWS SDK for Rubyのパフォーマンス
こちらの記事でも言及したようにAWS SDK for Ruby では、リソースにタグが大量に付与されている場合、一度に大量のリソースを取得に大幅に時間がかかることがあります。
以下はEBSを例に、タグ付与のあり・なしとで、リソースの取得(describe_volumes)の完了にどれくらいの時間を要したかを比較したグラフです(以下画像は前述記事の再掲)。
タグが大量に(この例では20個)付与されている場合、リソースの取得完了までに非常に時間がかかることが分かります。
こちらの記事では、処理に時間がかかっていたのはAPIのレスポンスのXMLをRubyのオブジェクトにパースする部分であると推定しました。
疑問
上記のようなパフォーマンスの変化が、AWS SDKの他の言語でも発生するか気になったので、確認してみようと思いました。
検証
今回、Rubyに加えて、Python、PHP、Go、Node.jsのAWS SDKでパフォーマンスを測定してみました。
対象は タグが20個付与されたEBS1000個 です。
クライアントは東京リージョンのLightSail(Ubuntu 18.04)です。
各言語で3回実施し、平均値を取っています。
各言語とSDKのVersionは後述。
検証結果
検証結果は以下の通りでした。どうやら 非常に時間がかかるのはRubyのSDKのみ のようでした。
他の言語については、本件に関する懸念はとりあえずは無くて良さそうです。
おわりに/感想
今回のような構成で処理に非常に時間がかかるのはAWS SDK for Ruby のみのようです。
RubyのSDKについても内部的に使用されるライブラリの改善等でパフォーマンスは改善されるかもしれませんので、今後に期待したいところです。
各言語とSDKのVersionと検証コード
言語 | SDK | |
---|---|---|
Ruby | 2.6.3 | 3.89.1 |
PHP | 7.2 | 3.133.34 |
Python | 3.7.1 | 1.2 |
Node.js | 12.14.0 | 2.638.0 |
Go | 1.13.4 | 1.29.22 |
Ruby
require 'aws-sdk-ec2'
Aws.config.update(credentials: Aws::Credentials.new('',''))
ec2_client = Aws::EC2::Client.new(region: 'ap-northeast-1')
start_time = Time.now
ec2_client.describe_volumes
end_time = Time.now
colapsed_time = end_time - start_time
puts colapsed_time
PHP
<?php
require 'vendor/autoload.php';
use Aws\Ec2\Ec2Client;
$ec2Client = new Aws\Ec2\Ec2Client([
'region' => 'ap-northeast-1',
'version' => '2016-11-15',
]);
$time_start = microtime(true);
$result = $ec2Client->describeVolumes();
$time = microtime(true) - $time_start;
echo "{$time} 秒";
Python
import boto3
import time
ec2 = boto3.client('ec2')
start = time.time()
ec2.describe_volumes()
elapsed_time = time.time() - start
print ("elapsed_time:{0}".format(elapsed_time))
Node.js
var AWS = require('aws-sdk');
AWS.config.update({region: 'ap-northeast-1'});
var ec2 = new AWS.EC2();
const startTime = Date.now(); // 開始時間
ec2.describeVolumes({}, function (err, data) {
console.log(Date.now() - startTime);
});
Go
package main
import (
"fmt"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
)
func main() {
sess, _ := session.NewSession(&aws.Config{
Region: aws.String("ap-northeast-1")},
)
svc := ec2.New(sess)
input := &ec2.DescribeVolumesInput{}
start := time.Now()
svc.DescribeVolumes(input)
end := time.Now()
fmt.Printf("%f秒\n", (end.Sub(start)).Seconds())
}