10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MobingiAdvent Calendar 2018

Day 4

Lambda Layerを使ってAWS LambdaのCPU使用率を計測する

Last updated at Posted at 2018-12-03

はじめに

lambdaでは通常CPU使用率を気にする必要はありませんが、パフォーマンスチューニングをして実行時間を短くしようとした際に、処理のボトルネックがIOなのかCPUなのか知りたいと思うケースがあります。

その際に簡単なデコレータを用意してCPU使用率を計測できるようにして、その機能をLambda Layerで使えるようにしてみました。

なおpython3の話です。

概要

  • psutilを使えばCPU時間を取得できる
  • 関数の実行前後でCPU時間を取得するデコレータ関数を作る
  • その関数をLambda Layerとしてデプロイする
  • Lambda関数でLayerをインポートしてのエントリポイントにデコテータをつける

詳細

psutilを使ったデコレータ関数を用意する

psutlを使えばCPU時間が取れます。

import psutil
psutil.cputimes()
結果
scputimes(user=344.21, nice=2.71, system=38.98, idle=39275.96, iowait=5.9, irq=0.0, softirq=7.84, steal=13.8, guest=0.0, guest_nice=0.0)

psutil.cpu_timesを使って関数実行前後にCPU時間を取得し、その差分からCPU使用率を取得するデコレータ関数を作成します。

from functools import wraps
from psutil import cpu_times

def cpu_trace(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        before = cpu_times()._asdict()
        result = func(*args, **kwargs)
        after = cpu_times()._asdict()

        increment = {}
        for key in after.keys():
            increment[key] = after[key] - before[key]
        total = sum(increment.values())
        rate = dict( (key, value / total ) for key, value in increment.items())
        print(rate)

        return result

    return wrapper

cpu_timesの戻り値はnamed_tupleなので、そのままでは各要素の値を計算し辛いです。なので_asdict()を読んでdict型で保存しています。
後はafterの各状態からbeforeの各状態を引いて差分を計算すれば関数実行中にどれだけCPU時間が増加したかわかります。それを元に各状態(idle, nice, user, ...)の比率を計算します。

作ったデコレータをLambda Layerとしてデプロイする

作ったデコレータをSAMでデプロイする設定を上のリポジトリにあげてます。
Lambda Layerで作るPython用パッケージはpythonという名前のディレクトリに配置されるようなディレクトリ構成にする必要があります。

workdir(ContentUri)
└── python
    ├── psutil
    ├── psutil-5.4.8.egg-info
    └── traceutil
        ├── __init__.py
        └── cpu_trace.py

Lambda LayerはCloud Formationのpackageとdeployでアップロード出来ます。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Lambda Layers to measure cpu in Python3 applications.

Resources:
  CpuTrace:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: AWSLambda-Python3-TraceUtil
      Description: Lambda Layers to measure cpu in Python3 applications.
      ContentUri: workdir
      CompatibleRuntimes:
        - python3.6
        - python3.7
      RetentionPolicy: Retain
aws cloudformation package \
	--template-file sam.yml \
	--s3-bucket $S3_BACKET \
	--s3-prefix $S3_PREFIX \
	--output-template-file .template.yml

aws cloudformation deploy \
	--template-file .template.yml \
	--stack-name $STACK_NAME

lambdaのエントリポイントにデコレータを追加する

あとはLambdaFunctionsのLayersに先程のLayerを追加した後にエントリポイントにデコレータを記述するだけです。

import json
from traceutil import cpu_trace
import time 

@cpu_trace
def lambda_handler(event, context):
    time.sleep(1)

    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

結果の確認

結果はCloudwatch Logsで見れます

結果
Function Logs:
START RequestId: eff78e17-e3ee-11e8-a1bb-97928c2e9342 Version: $LATEST
{'user': 0.0, 'nice': 0.0, 'system': 0.0, 'idle': 1.0, 'iowait': 0.0, 'irq': 0.0, 'softirq': 0.0, 'steal': 0.0, 'guest': 0.0, 'guest_nice': 0.0}
END RequestId: eff78e17-e3ee-11e8-a1bb-97928c2e9342
REPORT RequestId: eff78e17-e3ee-11e8-a1bb-97928c2e9342	Duration: 1001.90 ms	Billed Duration: 1100 ms 	Memory Size: 128 MB	Max Memory Used: 25 MB	

終わりに

LambdaのCPU使用率を計算したかったのでデコレータを使って計測できるLambda Layerを作ってみました。
こういうユーティリティっぽいものにも使えてLambda Layer便利ですね。

10
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?