さゆフィクション http://it.kensan.net/it aws wordpress などなどゆるーく書いてます Sun, 31 Mar 2024 06:56:44 +0000 ja hourly 1 https://wordpress.org/?v=6.4.3 https://it.kensan.net/wp-content/uploads/2023/03/cropped-icon-32x32.png さゆフィクション http://it.kensan.net/it 32 32 AWS ECS Fargateは1分間にいくつまで数えられるか-Linux/ARM64とLinux/X86_64の性能比較 https://it.kensan.net/aws-ecs-fargate%e3%81%af1%e5%88%86%e9%96%93%e3%81%ab%e3%81%84%e3%81%8f%e3%81%a4%e3%81%be%e3%81%a7%e6%95%b0%e3%81%88%e3%82%89%e3%82%8c%e3%82%8b%e3%81%8b-linux-arm64%e3%81%a8linux-x86_64%e3%81%ae.html Sun, 31 Mar 2024 04:07:12 +0000 https://it.kensan.net/?p=1781 AWS ECS Fargateについて、CPU(Linux/ARM64とLinux/X86_64)ごとに、1分間にいくつまで数えられるか調べてみました。

AWSの記事に以下の記載がありますが、実際にどれくらい性能が違うの?という点について調査するために、Fargateにカウントアップさせて、1分間にいくつまで数えられるかやってみました!!

AWS Graviton2 プロセッサは、64 ビットの Arm Neoverse コアを使用してアマゾンウェブサービスがカスタムビルドしたもので、Graviton2 を搭載した Fargate は、同等のインテル x86 ベースの Fargate に比べて、最大 40% の料金性能向上と 20% の低コストを実現し、

AWS Graviton2 Processors を搭載した AWS Fargate for Amazon ECS を発表

上記のAWSの記載をまとめると以下のようになると思います。

Linux/ARM64とLinux/X86_64の比較

Linux/ARM64(Graviton2)の方が、最大 40% の料金性能向上
Linux/ARM64(Graviton2)の方が、20% の低コスト
→Linux/ARM64(Graviton2)の方が安くて早い

では、実際に、Linux/ARM64(Graviton2)とLinux/X86_64(インテルCPU)の比較検証をしていきます。

検証ではカウントアップするだけという簡単なプログラムを使用していきます!

 

検証条件

まずは、検証条件についてです。

プログラム言語

使用するプログラム言語:python

ECS Fargate タスク性能

CPU:1vCPU

メモリ:2 GB

使用したプログラム

import time
import timeout_decorator

# 60秒でタイムアウト
@timeout_decorator.timeout(60)
def test():
    cnt = 0
    while True:   # タイムアウトするまで、ひたすらカウントアップ
        if cnt % 10000 == 0:
            print(cnt)
        cnt += 1

if __name__ == '__main__':
    try:
        test()
    except:
        print ("test timed out ")

使用したDockerファイル

FROM python:3.12

RUN pip install timeout-decorator

# 検証用プログラムをコピー
COPY . .

# コンテナ起動時に検証用プログラムを実行
CMD ["python", "./test.py"]

検証結果

Linux/ARM64(Graviton2)

<検証方法>

  1. ビルドし、ECRにイメージをpush
  2. ECSタスク定義の「オペレーティングシステム/アーキテクチャ」でLinux/ARM64を指定
  3. タスクを起動

<検証結果>

カウントアップできた数:702,420,000

Linux/X86_64(インテルCPU)

<検証方法>

  1. ビルドし、ECRにイメージをpush
  2. ECSタスク定義の「オペレーティングシステム/アーキテクチャ」でLinux/X86_64を指定
  3. タスクを起動

<検証結果>

カウントアップできた数:558,450,000

検証結果比較

  • Linux/ARM64(Graviton2)
    • カウントアップできた数:702,420,000
  •  Linux/X86_64(インテルCPU)
    • カウントアップできた数:558,450,000
  • Linux/ARM64(Graviton2)の方が、1.4億くらい多くカウントできました
    • Linux/ARM64(Graviton2)の方が、26%程度性能が良い結果です!!

まとめ

以下のAWS記事情報を前提に検証しました。今回やってみた簡単なカウントアップの検証では、性能はLinux/ARM64(Graviton2)の方が、26%程度高い結果となりました。コストが20%程度低いことから、料金性能は以下の「最大 40% の料金性能向上」とほぼ一致と思いますー

Linux/ARM64とLinux/X86_64の比較

Linux/ARM64(Graviton2)の方が、最大 40% の料金性能向上
Linux/ARM64(Graviton2)の方が、20% の低コスト
→Linux/ARM64(Graviton2)の方が安くて早い

]]>
Lambdaのタイムアウト検知の仕方とタイムアウト時の対処法・調査方法 https://it.kensan.net/lambda-timedout.html Mon, 08 Jan 2024 07:10:12 +0000 https://it.kensan.net/?p=717 Lambdaのタイムアウトについて書いていきまーす!

具体的には、以下の内容について、記載します。

本記事でやること
  • Lambdaのタイムアウトの検知
    • ログからタイムアウトの有無を確認する
    • CloudWatchのメトリクスフィルタを使用してタイムアウトをメトリクス化(可視化)する方法
  • タイムアウト時の対処法

まずタイムアウトの検知方法からみていきます。

タイムアウトの検知方法

ログからタイムアウトを検知可能です。

ログを検索してタイムアウトの有無を確認する

Lambdaタイムアウト時には「Task timed out」というフレーズがログに吐かれますので、CloudWatchLogsのログインサイトを使ってログを検索することで、タイムアウトの有無を確認できます。

対象のロググループを指定してログインサイト画面へ行き、以下のクエリを実行することで、タイムアウトのログを検索できます。

fields @timestamp, @message, @logStream, @log
| filter @message like 'Task timed out'
| sort @timestamp desc
| limit 20

次にメトリクスフィルタを使用して、タイムアウトをメトリクス化します!

メトリクスフィルタを使用してタイムアウトをメトリクス化する

メトリクスフィルタでタイムアウトをメトリクス化し、メトリクスのグラフ表示でタイムアウトを確認する方法です。

これにより、タイムアウトの回数や頻度を可視化できます。

メトリクスフィルターとは?という方は以下の記事をご参照ください。

CloudWatchLogsのメトリクスフィルターの使い方ーログデータをメトリクス化して監視する
メトリクスフィルターを使いCloudWatchLogsのログデータを 「CloudWatchのメトリクスで見える化する」「メトリクスを監視してアラートをあげる」ということをやってみます。JSONログデータのメトリクス化も可能です。メトリクス化ができれば監視は通常のアラーム設定と同様となります
  1. AWSマネージメントコンソール画面からCloudWatchダッシュボードを表示
  2. ロググループリンクを押下する
  3. メトリクスフィルタータブを開く
  4. 「メトリクスフィルターを作成」ボタンを押下
メモリクスフィルターを作成

メモリクスフィルターを作成

以下の画面が表示されるので、「フィルターパターン」を入力します。

フィルターパターンに「Task timed out」と入力します。

フィルタパターンを設定して、Nextボタンを押下すると

メトリクスの割り当て画面が表示されます。以下の設定をしてNextボタンを押下します。

  • フィルター名:適切なもの
  • メトリクス空間:CloudWatchのメトリクスの名前空間を指定します。メトリクスフィルターであることが分かりやすいものを入力すると良いです
  • メトリクス名:どのようなメトリクスなのか分かりやすい名前をつけると良いです。
  • メトリクス値:「1」を指定します

Review and confirm画面が表示されるので、「メトリクスフィルターを作成」ボタンを押下します。

AWSマネージメントコンソール画面からCloudWatchダッシュボードを表示して、すべてのメトリクスを押下して作成したメトリクスを選択するとグラフを確認できます。

また、作成したメトリクスでアラームを設定し、エラーが起きた時にメールやSlackなどに通知をすることも可能です。

タイムアウト時の対処法

公式記事にトラブルシューティングの方法が記載されています。

Lambda 関数呼び出しタイムアウトエラーのトラブルシューティング | AWS re:Post
コードの変更をデプロイしていなくても、AWS Lambda 関数が断続的にタイムアウトします。Lambda 関数呼び出しタイムアウトの問題をトラブルシューティングおよび防止するにはどうすればよいですか?

タイムアウト時の対処法は大きく3つと読み取れます

3つの対処法

AWS SDK の再試行とタイムアウト設定の見直し
タイムアウト時間を延ばす
メモリを増やす

まずは、AWS SDK の再試行とタイムアウト設定の見直しについて書いていきます!

AWS SDK の再試行とタイムアウト設定の見直し

以下にAWS SDK の再試行のデフォルト設定が記載されています。

AWS SDK を使用するときの Lambda 関数の再試行とタイムアウトに関する問題のトラブルシューティング | AWS re:Post
AWS SDK を使用して AWS Lambda 関数を呼び出す際に、関数がタイムアウトするか、API リクエストが応答を停止するか、API アクションが重複します。これらの問題の解決方法を教えてください。

これを現在のLambdaタイムアウト値と見比べ調整する感じです。

特に、GoとJavaScript/Node.jsは、接続タイムアウトの設定がないため、注意が必要です。

次は、タイムアウト時間を延ばす対策です。

タイムアウト時間を延ばす

こちらは、一旦タイムアウト値を伸ばして様子をみてみようという作戦です。

タイムアウト時間を延ばすことで、アプリケーションログが出力され、時間を要している箇所の特定ができるといったことが期待できます。

次はメモリを増やす対策です。

メモリを増やす

メモリを増やすことで

  • 呼び出し時間のレイテンシーを短縮
  • コンピューティング性能を向上

が期待できるようです。簡単にいうと早くなると言うことですね。

メモリを増やせば必ず解決する訳ではないので、メモリを増やしたうえで経過観察が必要となります。

それでも解決しないとき

Lambda Insights を有効化して、リソースの状態を確認してみるのが良いです。

Lambda Insightsの有効化方法は以下をご参照ください

AWS Lambda Insightsを有効化する方法と無効化する方法
AWS Lambda Insightsの有効化と無効化の切り替えは簡単に行えます。Lambda Insightsは有料ですので、エラー発生時など調査が必要な時だけ有効化、不要な時は無効化した方がいいと思います。Lambda関数の実行数に応じて料金も増えていくので、実行数が多い場合は要注意かと思います

X-Ray でも時間を要している箇所(ボトルネック)の確認が可能です。

AWS LambdaでX-Rayを有効化する方法と無効化する方法
AWS Lambda で X-Rayの有効化と無効化の切り替えは簡単に行えます。X-Rayは有料ですので、パフォーマンスに問題発生時など調査が必要な時だけ有効化、不要な時は無効化した方がいいと思います。Lambda関数の実行数に応じて(トレースする数に応じて)料金も増えていくので、実行数が多い場合は要注意かと思います

Lambda InsightsとX-Rayのどちらを使えば良いかで迷ったら、以下の基準で判断します。

  • サーバリソースの状況を確認したい場合:Lambda Insights
  • 間を要している箇所(ボトルネック)を確認したい場合:X-Ray
]]>
古いMacBookでディスクが容量足りなくなったので、外付けSSDにOSインストールして使ったら快適になった https://it.kensan.net/old_macbook_disk.html Sun, 07 Jan 2024 05:14:47 +0000 https://it.kensan.net/?p=1758 古いMacBookでディスクが容量足りなくなったので、外付けSSDにOSインストールして使ったら快適になったという話を記載します。

私のMacBookは「Retina, 13-inch, Early 2015」です。

ディスク容量は121GBです。

ディスク容量が足りません。必要なファイルを外付けSSDに移動したり、不要なファイルを削除したりして、ディスク容量を空ける日々を送っていませした。

そろそろ、買い替えようかな、でもお金ないな〜という日々です。

そんな中、SSDにOSインストールして使えばいいじゃんと思いつきました!

実際にやってみたので、手順を書いておきます。

では、外付けSSDにOSインストールして、MacBookを使う方法を記載してきます。

 

外付けSSDにOSインストールして、MacBookを使う方法

まず、私が使用しているMacBookとSSDについて記載します。

使用したMacBookとSSDについて

使用しているMacBook

Retina, 13-inch, Early 2015です。

OSはmacOS mojaveです。

SSDについて

500GBのSSDを用意しました。

外付けSSDにOSインストールする方法

実際に外付けSSDにOSをインストールしていきます。

外付けSSDの準備

1. 外付けSSDをmacにさします

2. アプリケーションから「ディスクユーティリティ」を起動します

    • 「ディスクユーティリティ」が見つからない場合は、Launchpadで「ディスクユーティリティ」を検索します

3. 「ディスクユーティリティ」の左上のメニューで、「すべてのデバイスを表示」を選択します

macディスクユーティリティ

macディスクユーティリティ

4.「ディスクユーティリティ」で、挿入したSSDを選択します

5. 「ディスクユーティリティ」上部の消去ボタンを押下します

6. フォーマット「Mac OS拡張(ジャーナリング)、方式「GUIDパーティションマップ」を選択して、消去します

OSのダウンロード

インストールしたいmacOSのダウンロードをします。

私はMontereyをダウンロードしました。以下のリンクからダウンロードできます。

macOS Monterey 12

外付けSSDにOSインストールする

ダウンロードしたOSファイルをダブルクリックしてインストール画面を表示します。

ダウンロードしたOSファイルが見つからない場合は、Finderの検索ボックスにOS名を入力して探せます。

同意して、以下の画面まで行ったら、インストール先ディスクで外付けSSDを選択して、インストールします。

macOSを外付けSSDにインストール

macOSを外付けSSDにインストール

インストール完了まで、1時間くらいかかります。

外付けSSDのOSでMacを起動する方法

外付けSSDをさした状態でMac起動すると、外付けSSDのOSでMac起動

外付けSSDを抜いた状態でMac起動すると、内臓SSDのOSでMac起動

となるようです。外付けSSDの抜き差しで、起動するOSを切り替えられるので楽チンです。

まとめ

時間はかかりますが、簡単に外付けSSDにmacOSをインストールして起動することができました。

外付けでも、SSDなので結構高速に動作します!

インストール後に、「情報の転送」をすることで、内臓SSDのファイルは、外付けSSDに入るので、OSインストール後のファイル移行などは不要です。

以下のように、内臓のSSD容量を増やす方法もあるようですが、不器用な私には不向きな気がして、今回は外付けSSDにOSをインストールしてみました。。

MacBook Pro 2015年モデルを最新NVMe SSDで延命、改造手順を全紹介! Samsung SSD 970 EVO PlusでMacのストレージを大容量・高速化 text by 坂本はじめ
Apple製品は独自規格のパーツを積極的に使用しており、市販のPCパーツでアップグレードが難しいことが知られているが、2015年以前のMacBook ProであればSSDを最新のNVMe SSDにアップグレードできる場合がある。
]]>
AWS Lambdaのメモリ使用率と処理速度 https://it.kensan.net/lambda-memory-over.html Tue, 02 Jan 2024 23:28:17 +0000 https://it.kensan.net/?p=1738 AWS Lambdaのメモリ使用率と処理速度について調べてみました。

具体的には、以下についてLambdaを動かして試しました。

  • メモリ使用率が100%になるとエラーが起きたりするか?
  • メモリ使用率が高いと速度劣化するか?

まず、先に調査結果を書いちゃいます。以下の通りです。

調査結果

・メモリ使用率が100%になるとエラーが起きたりするか?
→エラーにはならない!
・メモリ使用率が高いと速度劣化するか?
→速度劣化する

では早速、調査していきます!

メモリ使用率が100%になるとエラーが起きたりするか?について調査

調査方法

まず調査方法についてです。

以下の条件で調査しました。

前提条件

本記事では以下の条件で、調査しました。

言語:Python 3.12

Lambdaのタイムアウト設定:29

Lambdaのメモリ:128MB

調査で使用したソースコード

以下のソースを使用して調査しました。

import sys
import time
def lambda_handler(event, context):
    mem_test = []
    start = time.perf_counter()
    for i in range(5000000):
        mem_test.append(str(i))
        if i % 50000 == 0:
            print ('num:'+str(i))
            end = time.perf_counter()
            print(f"{end - start:.3f} s.")
            start = time.perf_counter()

ざっくり、以下のような処理のプログラムです。

  •  500万ループの中で、変数:mem_testに要素を追加
    • 要素を追加してメモリ使用量をあげる
    • 5万件おきにログ出力して、実行速度をログ出力

実行してみる

以下の実行結果になりました。

Task timed out after 29.55 seconds
Duration: 29548.53 ms Billed Duration: 29000 ms Memory Size: 128 MB Max Memory Used: 128 MB Init Duration: 79.60 ms

調査結果

処理がLambdaのタイムアウト時間以内に終わらずにエラーとなっていますが、メモリ全てを使ってもエラーにはならないことがわかりました。

以下の通り、ループを200万に減らして実行すると、タイムアウトせず、正常に処理終了しました。

<ソースコード>

import sys
import time
def lambda_handler(event, context):
    mem_test = []
    start = time.perf_counter()
    for i in range(2000000):
        mem_test.append(str(i))
        if i % 50000 == 0:
            print ('num:'+str(i))
            end = time.perf_counter()
            print(f"{end - start:.3f} s.")
            start = time.perf_counter()

<実行結果>

Duration: 9003.65 ms Billed Duration: 9004 ms Memory Size: 128 MB Max Memory Used: 128 MB Init Duration: 116.19 ms

 

次は、メモリ使用率が高いと速度劣化するか?についてみていきます。

メモリ使用率が高いと速度劣化するか?

上記の「メモリ使用率が100%になるとエラーが起きたりするか?」と同様の前提条件で、確認していきます。

調査①メモリ解放せずに500万ループする

以下のソースで確認していきます。

import sys
import time
def lambda_handler(event, context):
    mem_test = []
    start = time.perf_counter()
    for i in range(5000000):
        mem_test.append(str(i))
        if i % 50000 == 0:
            print ('num:'+str(i))
            end = time.perf_counter()
            print(f"{end - start:.3f} s.")
            start = time.perf_counter()

上記の「メモリ使用率が100%になるとエラーが起きたりするか?」と同様ですが、ざっくり、以下のような処理のプログラムです。

  •  500万ループの中で、変数:mem_testに要素を追加
    • 要素を追加してメモリ使用量をあげる
    • 5万件おきにログ出力して、実行速度をログ出力

調査①実行結果

途中でタイムアウトしたが、5万件毎の処理速度は0.220 s程度。メモリは限界まで(128MBまで)使っている。

Task timed out after 31.03 seconds
Duration: 31029.20 ms Billed Duration: 29000 ms Memory Size: 128 MB Max Memory Used: 128 MB Init Duration: 81.84 ms

調査②メモリ解放しつつに500万ループする

以下のソースコードで調査します。

調査①との違いは、最後の行で「mem_test = []」を使い、5万件毎に初期化をして、メモリ解放している点です。

import sys
import time
def lambda_handler(event, context):
    mem_test = []
    start = time.perf_counter()
    for i in range(5000000):
        mem_test.append(str(i))
        if i % 50000 == 0:
            print ('num:'+str(i))
            end = time.perf_counter()
            print(f"{end - start:.3f} s.")
            start = time.perf_counter()
            mem_test = []

調査②実行結果

途中でタイムアウトせず、5万件毎の処理速度は0.161s程度。メモリは36MBまで使っている。

Duration: 18596.18 ms Billed Duration: 18597 ms Memory Size: 128 MB Max Memory Used: 36 MB Init Duration: 83.56 ms

 

調査結果

適切にメモリ解放する方が、メモリ解放処理の時間を差し引いても早いことがわかりました。

まとめ

以下の結果となりました〜

調査結果まとめ

・メモリ使用率が100%になるとエラーが起きたりするか?
→エラーにはならない!
・メモリ使用率が高いと速度劣化するか?
→速度劣化する

]]>
API Gateway(REST API)とLambda(Python)でBOM付きUTF8なCSVをレスポンスする方法 https://it.kensan.net/api-gateway-lambdapython-bom-utf8-csv.html Thu, 19 Oct 2023 18:51:22 +0000 https://it.kensan.net/?p=1741 API Gateway(REST API)とLambda(Python)の構成で、LambdaでBOM付きUTF8のCSVを作成して、API Gateway経由でCSVをレスポンスする方法を記載します。

BOM付きUTF8とすることで外字が文字化けしないCSVをAPI Gateway経由でダウンロードできます。

やること

AWSの構成はAPI GatewayとLambda
使用する言語はPython
外字が文字化けしないCSVをダンロードできるようにする
→BOM付きUTF8とすることで文字化け対策ができます。

Lambdaの作成

以下のソースコードでLambdaを作成します。



def lambda_handler(event, context):
    body_str = """column1,column2
"㐂","昱"
"""
    return {
        'statusCode': 200,
        'isBase64Encoded': True,
        'headers': {
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Credentials': True,
            'Content-Type': "application/vnd.ms-excel",
            'Content-disposition': "attachment; filename=hoge.csv" # CSVファイル名を指定
        },
        'body': f'\ufeff{body_str}' # BOMを設定
    }

「body_str」がレスポンスするCSVの中身になりますので適宜調整します。

次はAPI Gatewayです

API Gatewayの設定

REST APIを新規作成します。特に気にする設定項目はないので、とにかくREST APIを作成です。

次にメソッドを追加します。このとき、以下の画面のように「Lambda プロキシ統合の使用」にチェックを入れておきます。

API-Gatewayメソッド追加

API-Gatewayメソッド追加

Lambda プロキシ統合の使用」にチェックを入れないと、Lambdaで返却したJSONがそのままレスポンスボディとして返却され、CSVではなく、ヘッダ情報を含んだJSONがレスポンスされてしまう現象にハマります。

最後にAPIをデプロイします。

動作確認

API GatewayのステージからURLを確認し、ブラウザでアクセスします。

この時、メソッドやパスは、作成したAPI Gatewayに沿ったものを設定する必要があります。

URLにアクセスするとCSVダウンロードができ、文字化けもしていないかと思います。

まとめ

API Gateway(REST API)とLambda(Python)の構成で、CSVダウンロードできました!

Lambdaにはリクエストとレスポンスの上限サイズとして、それぞれ 6 MBが上限という制限があります。6MB以上のCSVはLambdaではレスポンスできないということです。

大きいCSVファイルを扱うには、LambdaでCSVを作成して、S3に保存して、ユーザーにはS3のデータをダウンロードしてもらった方が良さそうですね。

]]>
AWS Lambdaは1秒間にいくつまで数えられるか-メモリ毎の性能調査 https://it.kensan.net/aws-lambda%e3%81%af1%e7%a7%92%e9%96%93%e3%81%ab%e3%81%84%e3%81%8f%e3%81%a4%e3%81%be%e3%81%a7%e6%95%b0%e3%81%88%e3%82%89%e3%82%8c%e3%82%8b%e3%81%8b.html Sat, 19 Aug 2023 02:57:18 +0000 https://it.kensan.net/?p=1718 AWS Lambdaは1秒間にいくつまで数えられるか調べてみました。

前提として、メモリと処理性能と料金は比例しています。

メモリを倍にすれば、CPUの処理性能と料金は倍になるということです。

本記事では、上記の前提が本当なの?を、AWS Lambdaは1秒間にいくつまで数えられるか確認するプログラムを作成して、メモリ量を変更してLambda実行して検証していきます。

まずは、前提としている「メモリと処理性能と料金は比例しています」についてどこからきているか記載していきます。

前提知識

まずは、前提知識です。以下の点についてみていきます。

  • 料金に関する前提知識
  • 設定・性能に関する前提知識

料金に関する前提知識

メモリ (MB) 1 ミリ秒あたりの料金
128 0.0000000021USD
512 0.0000000083USD
1,024 0.0000000167USD
料金 - AWS Lambda |AWS
AWS Lambda では、使用した分の料金が発生します。料金は、関数に対するリクエストの数とコードの実行時間に応じて請求されます。
料金に関する前提知識

メモリと料金は比例している
→メモリを倍にすれば、1 ミリ秒あたりの料金も倍になる。

 

設定・性能に関する前提知識

シンプルな Lambda 関数の場合にのみ 128 MB を選択するのがベストプラクティスです。

メモリの量によって、関数で使用できる仮想 CPU の量も決まります。メモリを追加すると、それに比例して CPU の量が増え、それによって使用可能な計算能力も増加します。

メモリと計算能力は AWS Lambda のコストにどのように影響しますか?
メモリと計算能力が AWS Lambda のコストにどのように影響するかを把握したいと考えています。
設定・性能に関する前提知識

シンプルな Lambda 関数の場合はメモリを128 MBに設定することがベストプラクティス
メモリの量に応じて、CPUの計算能力も増える

では検証していきます。

検証条件

まずは検証条件から記載していきます。

CPU

CPUアーキテクチャは「x86_64」で検証しました。

言語と検証用プログラム

次に言語と検証用プログラムについてです。

言語

言語は「Python 3.11」を使用しました。

検証用プログラム

検証用に使用したプログラムは以下のものとなります。

import os

def lambda_handler(event, context):
    os.system('cat /proc/cpuinfo')   # CPUの確認
    cnt = 0
    while True:   # タイムアウトするまで、ひたすらカウントアップ
        if cnt % 1000 == 0:
            print(cnt)
        cnt += 1

タイムアウト設定

タイムアウトは1秒に設定

検証結果

検証結果は以下の通りです。

  • CPUは全ての結果において「Intel(R) Xeon(R) Processor @ 2.50GHz」が使用されている
  • 多少ばらつきはあるが、メモリを増やすと、処理できる件数(CPU性能)もアップする
    • メモリを倍にすれば、処理速度も上がるので、料金が倍になることはなさそう
      • プログラム自体の作りによっても結果は変わってくると思うので断言できず…
メモリ カウントアップできた数 CPU 128MBをベースとして、メモリは何倍か 128MBをベースとして、何倍処理できたか
128MB 638000 Intel(R) Xeon(R) Processor @ 2.50GHz
512MB 2625000 Intel(R) Xeon(R) Processor @ 2.50GHz 4.00倍 4.15倍
1GB 4192000 Intel(R) Xeon(R) Processor @ 2.50GHz 7.81倍 6.57倍
1.5GB 5738000 Intel(R) Xeon(R) Processor @ 2.50GHz 11.71倍 8.99倍
2GB 7612000 Intel(R) Xeon(R) Processor @ 2.50GHz 15.63倍 11.93倍
2.5GB 10157000 Intel(R) Xeon(R) Processor @ 2.50GHz 19.53倍 15.92倍

まとめ

「メモリと処理性能と料金は比例しています」が本当?を調べました。

結果は、本当でした。

まとめ

多少ばらつきはあるが、メモリを増やすと、処理できる件数(CPU性能)もアップする(メモリを倍にすれば、処理速度も上がるので、料金が倍になることはなさそう)
→プログラム自体の作りによっても結果は変わってくると思うので断言できず…

CPUはメモリ量に関係なく「Intel(R) Xeon(R) Processor @ 2.50GHz」が使用されている

]]>
MySQLのInnoDBとMyISAMのパフォーマンス比較をしてみました https://it.kensan.net/mysql-innodb-myisam-performance.html Fri, 18 Aug 2023 20:05:08 +0000 https://it.kensan.net/?p=1710 MySQLのInnoDBとMyISAMのパフォーマンス比較をしてみましたー

対象のMySQLのバージョンは5.7と8.0です。

結論としては、

  • INSERTはMyISAMの方が早い
  • SELECT・UPDATE・DELETEは
    • 8.0ではInnoDBの方が早い
    • 5.7ではSELECT・DELETEはMyISAMの方が早い。UPDATEはInnoDBの方が早い

という結果でしたー!

なお、MySQLのバージョンごとのサポート期限は以下のようになっています。

MySQLバージョン MySQL AWS RDSのMySQL AWS AuroraのMySQL
5.7 2023年10月31日 2023 年 10 月 2024 年 10 月 31 日

(Aurora バージョン2)

8.0 2026年4月30日 未定 未定

(Aurora バージョン3)

検証条件

  • MySQL5.7-MyISAMで、1万件のデータ登録をした後、SELECT・UPDATE・DELETE
  • MySQL5.7-InnoDBで、1万件のデータ登録をした後、SELECT・UPDATE・DELETE
  • MySQL8.0-MyISAMで、1万件のデータ登録をした後、SELECT・UPDATE・DELETE
  • MySQL8.0-InnoDBで、1万件のデータ登録をした後、SELECT・UPDATE・DELETE

比較結果詳細

MySQL5.7 MySQL8.0
MyISAM InnoDB MyISAM InnoDB
1万件データ作成

24.96 sec

53.24 sec

21.39 sec

48.92 sec

1万件カウント

0.00016000 sec

0.00359175 sec

0.00018900 sec

0.00850275 sec

1SELECT

0.00127125 sec

0.00401250 sec

0.07204400 sec

0.00575250 sec

1UPDATE

0.06670350 sec

0.01640200 sec

0.02672875 sec

0.01512700 sec

1DELETE

0.00380375 sec

0.00935400 sec

0.02560125 sec

0.01409000 sec

準備

検証環境:AWS RDS
インスタンスクラス:db.t3.micro


-- 区切り文字を「//」に変更する
DELIMITER //

-- make_sample_dataというテストデータ作成用プロシージャーを作成する

create procedure make_sample_data(in i int)
begin
  declare count int default 0;
  -- 繰り返し
  while count < i do
    set count = count + 1;
    INSERT INTO user VALUES(count, MOD(count,2),CONCAT('usr_name_',count));
  end while;
end
//
-- 区切り文字を「;」に戻す
DELIMITER ;

MySQL5.7 MyISAM

create table user(
id INT,
type INT,
name VARCHAR(255)
) engine MyISAM;

 

mysql> select version();
+------------+
| version()  |
+------------+
| 5.7.41-log |
+------------+
1 row in set (0.00 sec)

◾️1万件データ作成

call make_sample_data(10000);
Query OK, 1 row affected (24.96 sec)

◾️1万件カウント

select count(*) from user;
+----------+
| count(*) |
+----------+
|    10000 |
+----------+
0.00016000 

◾️1件SELECT

select * from user where id = 5000;
+------+------+---------------+
| id   | type | name          |
+------+------+---------------+
| 5000 |    0 | usr_name_5000 |
+------+------+---------------+
0.00127125 

◾️1件UPDATE

update user set name = 'name_5001' where id = 5001;
0.06670350 

◾️1件DELETE

delete from user where id = 5002;
0.00380375 

MySQL5.7 InnoDB

create table user(
id INT,
type INT,
name VARCHAR(255)
) engine InnoDB;

◾️1万件データ作成

call make_sample_data(10000);
Query OK, 1 row affected (53.24 sec)

◾️1万件カウント

select count(*) from user;
+----------+
| count(*) |
+----------+
|    10000 |
+----------+
0.00359175 

◾️1件SELECT

select * from user where id = 5000;
+------+------+---------------+
| id   | type | name          |
+------+------+---------------+
| 5000 |    0 | usr_name_5000 |
+------+------+---------------+
0.00401250

◾️1件UPDATE

update user set name = 'name_500001' where id = 5001;
0.01640200 

◾️1件DELETE

delete from user where id = 5002;
0.00935400 

MySQL8.0 MyISAM

create table user(
id INT,
type INT,
name VARCHAR(255)
) engine MyISAM;
select version();
+-----------+
| version() |
+-----------+
| 8.0.32    |
+-----------+

◾️1万件データ作成

call make_sample_data(10000);
Query OK, 1 row affected (21.39 sec)

◾️1万件カウント

select count(*) from user;
+----------+
| count(*) |
+----------+
|    10000 |
+----------+
0.00018900 

◾️1件SELECT

select * from user where id = 5000;

+------+------+---------------+
| id   | type | name          |
+------+------+---------------+
| 5000 |    0 | usr_name_5000 |
+------+------+---------------+
0.07204400 

◾️1件UPDATE

update user set name = 'name_500001' where id = 5001;
0.02672875 

◾️1件DELETE

delete from user where id = 5002;
0.02560125

MySQL8.0 InnoDB

create table user(
id INT,
type INT,
name VARCHAR(255)
) engine InnoDB;

◾️1万件データ作成

call make_sample_data(10000);
Query OK, 1 row affected (48.92 sec)

◾️1万件カウント

select count(*) from user;
+----------+
| count(*) |
+----------+
|    10000 |
+----------+
0.00850275

◾️1件SELECT

select * from user where id = 5000;
+------+------+---------------+
| id   | type | name          |
+------+------+---------------+
| 5000 |    0 | usr_name_5000 |
+------+------+---------------+
0.00575250 

◾️1件UPDATE

update user set name = 'name_500001' where id = 5001;
0.01512700

◾️1件DELETE

delete from user where id = 5002;
0.01409000 

まとめ

MySQLのInnoDBとMyISAMのパフォーマンス比較をしてみましたー

結論としては、

  • INSERTはMyISAMの方が早い
  • SELECT・UPDATE・DELETEは
    • 8.0ではInnoDBの方が早い
    • 5.7ではSELECT・DELETEはMyISAMの方が早い。UPDATEはInnoDBの方が早い

という結果でしたー!

MyISAMとInnoDBの違いを比較した記事もありますので、よろしければ、ご参照くださいー

MySQL8.0でのMyISAMとInnoDBの違いを比較
MySQL8.0でのストレージエンジンのMyISAMとInnoDBの違いについて記載しています。 InnoDBには、トランザクション機能や外部キー機能がありますので、 MyISAMとInnoDBで迷ったら、多くの主要な機能が備わっているInnoDBを選択しましょ!
]]>
CloudFrontログのHTTP ステータスコード000について調べてみた https://it.kensan.net/cloudfront000.html Sat, 13 May 2023 03:11:24 +0000 https://it.kensan.net/?p=1697 CloudFrontログのHTTP ステータスコード000について、どのような場合に発生するか調べてみました。

CloudFrontログでHTTP ステータスコードが000のモノをよく見るけど、これはどういった時に発生するのか、無視していいモノなのか分かりませんでしたので、調べましたーという内容になります!

公式ガイドでは、以下の記載があります。

  • 000。この値は、サーバーがリクエストに応答する前に、ビューワーが接続を閉じたことを示します。サーバーがレスポンスの送信を開始した後にビューワーが接続を閉じた場合、このフィールドには、サーバーが送信を開始したレスポンスの HTTP ステータスコードが含まれます。
標準ログ (アクセスログ) の設定および使用 - Amazon CloudFront
ログファイルを使用してオブジェクトに対するユーザーリクエストに関する情報を取得します。

「ビューワーが接続を閉じたこと = ブラウザを閉じた」と考えていいものかという疑問です。

Lambda@Edgeを使ってSleepを入れながら確認した結果、HTTP ステータスコードが000は、ブラウザを閉じた場合など接続が切れた場合に発生することが分かりました!

接続が切れた場合なので、基本的に無視して良い(どうしようも無い)ログということです。

ポイント

<疑問>
CloudFrontログでHTTP ステータスコードが000のものは何者?
<調査方法>
Lambda@Edgeを使ってSleepを入れながら確認
<調査結果>
ブラウザを閉じた場合など接続が切れた場合に発生する

 

調査方法の詳細と調査結果を書いていきます!

調査方法

CloudFrontのオリジンをS3にして作成し、Lambda@Edgeを使ってSleepを入れながら確認しました。

まずは、調査の準備について記載します。

調査準備

CloudFrontとS3の作成

  1. S3バケットを作成
  2. CloudFrontのディストリビューションをオリジン:S3に設定して作成

次にSleepを入れるLambda@Edgeを作成します!

リクエスト時のLambda@Edge

以下のものを作成しておきます。

const sleep = (m) => {
  return new Promise((resolve) => setTimeout(resolve, m));
};
export const handler = async(event) => {
    await sleep(2000);
    return event['Records'][0]['cf']['request'];
};

レスポンス時のLambda@Edge

以下のものを作成しておきます。

const sleep = (m) => {
  return new Promise((resolve) => setTimeout(resolve, m));
};
export const handler = async(event, context, callback) => {
    await sleep(2000);
    callback(null, event.Records[0].cf.response);
};

調査実施

以下のイベントのタイミングで、上記で用意したLambda@Edgeを実行し、Sleepするようにします。Sleepしている間に接続を切ったら、どのようになるか確認していきます。

  • ビューワーリクエスト
  • オリジンリクエスト
  • ビューワーレスポンス
  • オリジンレスポンス

各イベントの詳細は以下をご参照ください。

Lambda@Edge 関数をトリガーできる CloudFront イベント - Amazon CloudFront
特定の CloudFront イベントを使用して、Lambda 関数の実行をトリガーできます。

ビューワーリクエスト

ビューワーリクエストに「リクエスト時のLambda@Edge」を設定して、CloudFrontにアクセスし、Sleep中に通信を切断します。

動作確認には「ブラウザ」と「curlコマンド」を使用しました。

アクセス中にブラウザのタブを閉じた場合の結果

HTTP ステータスコード(sc-status):000

x-edge-detailed-result-type:ClientCommError

curlコマンドのタイムアウトを1秒に設定して実行した場合の結果

<実行したコマンド>

curl --max-time 1 {url}

<結果>

HTTP ステータスコード(sc-status):000

x-edge-detailed-result-type:ClientCommError

次はオリジンリクエストです。

オリジンリクエスト

オリジンリクエストに「リクエスト時のLambda@Edge」を設定して、CloudFrontにアクセスし、Sleep中に通信を切断します。

アクセス中にブラウザのタブを閉じた場合の結果

HTTP ステータスコード(sc-status):000

x-edge-detailed-result-type:ClientCommError

curlコマンドのタイムアウトを1秒に設定して実行した場合の結果

<実行したコマンド>

curl --max-time 1 {url}

<結果>

HTTP ステータスコード(sc-status):000

x-edge-detailed-result-type:ClientCommError

次は、ビューワーレスポンスです。

ビューワーレスポンス

ビューワーレスポンスに「レスポンス時のLambda@Edge」を設定して、CloudFrontにアクセスし、Sleep中に通信を切断します。

アクセス中にブラウザのタブを閉じた場合の結果

HTTP ステータスコード(sc-status):000

x-edge-detailed-result-type:ClientCommError

curlコマンドのタイムアウトを1秒に設定して実行した場合の結果

<実行したコマンド>

curl --max-time 1 {url}

<結果>

HTTP ステータスコード(sc-status):000

x-edge-detailed-result-type:ClientCommError

次は、オリジンレスポンスです。

オリジンレスポンス

オリジンレスポンスに「レスポンス時のLambda@Edge」を設定して、CloudFrontにアクセスし、Sleep中に通信を切断します。

アクセス中にブラウザのタブを閉じた場合の結果

HTTP ステータスコード(sc-status):000

x-edge-detailed-result-type:ClientCommError

curlコマンドのタイムアウトを1秒に設定して実行した場合の結果

<実行したコマンド>

curl --max-time 1 {url}

<結果>

HTTP ステータスコード(sc-status):000

x-edge-detailed-result-type:ClientCommError

調査結果

以下のイベントのタイミングで接続を切った場合、結果は同じで、全てのケースで「HTTP ステータスコード000」が発生しました。

  • ビューワーリクエスト
  • オリジンリクエスト
  • ビューワーレスポンス
  • オリジンレスポンス

HTTP ステータスコード000の正体は、ブラウザの接続が切れたケースという結果となります。

ついでに、オリジンにALBを指定して、接続を切った場合、ALBのログがどうなるかについても調査しました!

オリジンにALBを指定して、接続を切った場合のALBログ調査

CloudFrontの調査と同様Lambda@EdgeでSleepを入れて調査しました。

ビューワーリクエスト中に接続が切れた場合

ログ出力されない

→オリジン(ALB)にリクエストが届いていない

オリジンリクエスト中に接続が切れた場合

ログ出力されない

→オリジン(ALB)にリクエストが届いていない

ビューワーレスポンス中に接続が切れた場合

HTTP ステータスコード200でログ出力

→ALB自体は正常終了

オリジンレスポンス中に接続が切れた場合

200

→ALB自体は正常終了

まとめ

以下の結果となりましたー!

CloudFrontログのHTTP ステータスコード000は何者?の疑問が解消されましたー!

まとめ

<疑問>
CloudFrontログでHTTP ステータスコードが000のものは何者?
<調査方法>
Lambda@Edgeを使ってSleepを入れながら確認
<調査結果>
ブラウザを閉じた場合など接続が切れた場合に発生する

]]>
AWS Fargateで使われているCPUについて調べてみた https://it.kensan.net/aws-fargate-cpu.html Fri, 12 May 2023 10:16:05 +0000 https://it.kensan.net/?p=1681 AWS FargateのCPUは何が使われているのか疑問でしたので、調べてみました。

ArmのCPUはAWS Graviton2 が使われています。

AWS Fargate の AWS Graviton2 のサポートを発表 – サーバーレスコンテナのコストパフォーマンスが最大 40% 向上 | Amazon Web Services
AWS Graviton2 プロセッサは、64 ビットの Arm Neoverse コアを使用して AWS が

しかし、IntelCPU(X86)の方はどのCPUを使用しているか明記されていないようですので、実験して調べました。

結果、以下のいづれかが使われていることがわかりました!

ポイント

調べたこと:FargateでIntelCPU利用時に、どのCPUが使われているか
→ArmのCPUはAWS
Graviton2 が使われてることが分かっているので調査対象外
調査結果:以下のいずれかが使われている
Intel(R) Xeon(R) Platinum 8375C CPU(EC2 M6i インスタンス相当)
Intel(R) Xeon(R) Platinum 8275CL CPU(EC2 C5 インスタンス 相当)

 

結果を書いてしまいましたが、上記結果に至るまでの調査方法を書いていきます。

調査方法

以下のDockerイメージを使わせていただきました。

Docker

上記Dockerイメージでは、コンテナ起動時にログにCPU名が出力されるので、ログを見てCPUを確認するという調査方法です。

具体的にやってこと

クラスタ作成
タスク定義作成
タスクの起動

まずは、クラスターを作成します!

クラスター作成

AWSマネージメントコンソール画面のECSダッシュボードから「クラスターの作成」ボタンを押下し、以下の設定でクラスターを作成します。

  • クラスター名:適切な名前
  • 上記以外、デフォルトのまま

次はタスク定義を作成します!

タスク定義の作成

AWSマネージメントコンソール画面のECSダッシュボードからタスク定義を選択し、「新しいタスク定義の作成」ボタンを押下し、以下の設定でタスク定義を作成する

  • タスク定義とコンテナの設定
    • タスク定義ファミリー:適切な名前
    • コンテナ – 1
      • 名前:適切な名前
      • イメージ URI:actions/lscpu:latest
      • 上記以外デフォルトのまま
    • 環境、ストレージ、モニタリング、タグの設定
      • 環境
        • CPU:.5VCPU
        • メモリ:1GB
    • 上記以外デフォルトのまま

次はタスクの作成(コンテナ立ち上げ)です!

タスクの作成

AWSマネージメントコンソール画面のECSダッシュボードで作成したクラスターを選択し、タスクタブ押下して、「新しいタスクの実行」ボタンを押下し、以下の設定で作成します。(このステップでコンテナを立ち上がります)

  • デプロイ設定
    • ファミリー:作成したタスク定義を指定
    • 上記以外デフォルトのまま
  • 必要なタスク:5
  • 上記以外はデフォルトのまま

調査結果

上記でタスクを立ち上げ、ログを確認したところ、CPUは以下の通りでした。

Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz

Intel(R) Xeon(R) Platinum 8275CL CPU @ 3.00GHz

Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz

Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz

Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz

まとめ

FargateでIntelCPU(X86)選択時に、どのCPUが使用されるかについて、明記されていなかったので、CPUにばらつきがある(起動タイミングによってCPUが変わる)のかなと思ったりしてました。

調査したところ、多少のばらつきはあり、EC2 M6iまたはC5 インスタンス相当のCPUが使われているという結果でした!

まとめ

調査内容:FargateでIntelCPU利用時に、どのCPUが使われているか
調査結果:以下のいずれかが使われている
Intel(R) Xeon(R) Platinum 8375C CPU(EC2 M6i インスタンス相当)
Intel(R) Xeon(R) Platinum 8275CL CPU(EC2 C5 インスタンス 相当)

]]>
AWS Aurora Serverless v2の用途や注意点 https://it.kensan.net/aws-aurora-serverless-v2.html Sat, 06 May 2023 02:47:37 +0000 https://it.kensan.net/?p=1626 Aurora Serverless v2について記載します。

具体的には以下のことについて記載していきます。

  • Aurora Serverless v2とは
  • 用途
  • 注意点

まずはAurora Serverless v2とは?について書いていきます。

Aurora Serverless v2とは

Aurora Serverless v2は、オンデマンドでAuto Scaling設定できるデータベースです。

以下の点について、具体的に記載していきます。

これから記載すること

性能
スケーリング
可用性

性能

ACUという単位で管理されることになります。

1ACUは、約2GB のメモリと、対応する CPU、ネットワークの組み合わせとなります。

ACUは最大、128 ACU を指定することができます。

ACUの最大はどれくらいのインスタンスかというと、メモリは128 ACU × 2GB = 256GBとなります。DBインスタンスクラスタイプがr6gの場合、以下の公式ページから、r6gかつメモリ:256GBのインスタンスを探して、db.r6g.8xlargeが最大ということになります。

Aurora DB インスタンスクラス - Amazon Aurora
DB インスタンスクラスによって、 Amazon Aurora DB インスタンスの計算とメモリの容量を決定します。
ACUの最大の時の性能例

インスタンスクラス:db.r6g.8xlarge
vCPU:32
メモリ(GB):256

 

スケーリング

Aurora Serverless v2は以下に記載されている通り、スケーリングが早く、アクセスのスパイクにも耐えたれそうです。(実際に耐えられるかどうかは、システムがDBへどれくらいの負荷をかけるか次第になるので、要検証ですね)

Amazon Aurora Serverless v2 は、ほんの一瞬で数十万ものトランザクションにスケールできます。スケールに応じて、容量をきめ細かい増分で調整し、アプリケーションが必要とする適切な量のデータベースリソースを提供します。

Amazon Aurora Serverless | AWS
Amazon Aurora Serverless では、管理する DB インスタンスはありません。データベースは、アプリケーションニーズに応じて、容量を自動的に起動、停止、および拡大または縮小します。

また、Aurora Serverless v2 では、以下のようなケースでもスケーリング可能なようです。

  • データベースの接続中
  • SQL トランザクション処理中
  • テーブルロック中
  • 一時テーブルの使用中

可用性

Aurora Serverless v2は、以下の特徴を持ち、高可用性を確立しています。

  • マルチ AZ 対応
  • 自動的フェイルオーバー

次は、用途について記載します。

用途

  • 変化の大きいアクセスやアクセス量が予測できない時
    アクセスが多い時と少ない時の落差が大きい場合や、アクセス量が予測できない場合、データベースは負荷に応じて、自動的にスケーリングしてくれます。
  • 開発時のAuroraの代替
    本番は、Auroraを使用している場合でも、開発環境は、Aurora Serverlessを利用するとコスト削減につながることあります。

次は、注意点です。

 

注意点

以下に注意点を記載します。

  • MySQLの場合、Aurora MySQL バージョン 3のみ対応しています
    • MySQLのバージョン8系しか対応していないということになります
  • ACUは最大、128 ACU(db.r6g.8xlargeくらい)が最大となっています
    • 最大が決まっているため、要注意です
  • Aurora Serverless v1 では Data API が使えましたが、v2ではData APIは使えません。
  • 費用の予測がしにくい
    • 最大ACUから最大の費用は算出することができますが、実際にどれくらいの費用となるかについては予測がしづらいです

まとめ

v1では、SQL実行中はスケーリングできないなどの制限がありましたが、v2では改善され用途が広がりそうですね。素晴らしーい!

]]>