きっかけ

自社サービス内で利用しているCloud Functionsの処理が少しもっさりしている感じがしたので、ランタイムによってどのくらい処理速度が変わるのか実験してみることにしました。

検証条件

2020年4月20日現在、Google Cloud Platformでは、以下のランタイムがサポートされています。

cloud functionsのランタイム一覧

今回は、この中で非推奨となっているNode.js 6以外のランタイムを利用してデフォルトで生成される”Hello world”プログラムをベースに検証を行っています。メモリの割当は、同一条件の256MiB、トリガ種別は、「HTTP」を利用します。

今回作成した検証環境

検証に利用したサンプルコード

function-1,function-2では、下記に示すgolangプログラムを利用しています。

package p

import (
    "encoding/json"
    "fmt"
    "html"
    "net/http"
)

// HelloWorld prints the JSON encoded "message" field in the body
// of the request or "Hello, World!" if there isn't one.
func HelloWorld(w http.ResponseWriter, r *http.Request) {
    var d struct {
        Message string `json:"message"`
    }
    if err := json.NewDecoder(r.Body).Decode(&d); err != nil {
        fmt.Fprint(w, "Hello World!")
        return
    }
    if d.Message == "" {
        fmt.Fprint(w, "Hello World!")
        return
    }
    fmt.Fprint(w, html.EscapeString(d.Message))
}

function-3,function-4では、下記に示すjavascriptプログラムを利用しています。

/**
 * Responds to any HTTP request.
 *
 * @param {!express:Request} req HTTP request context.
 * @param {!express:Response} res HTTP response context.
 */
exports.helloWorld = (req, res) => {
  let message = req.query.message || req.body.message || 'Hello World!';
  res.status(200).send(message);
};

function-5では、下記に示すpythonプログラムを利用しています。

def hello_world(request):
    """Responds to any HTTP request.
    Args:
        request (flask.Request): HTTP request object.
    Returns:
        The response text or any set of values that can be turned into a
        Response object using
        `make_response <http://flask.pocoo.org/docs/1.0/api/#flask.Flask.make_response>`.
    """
    request_json = request.get_json()
    if request.args and 'message' in request.args:
        return request.args.get('message')
    elif request_json and 'message' in request_json:
        return request_json['message']
    else:
        return f'Hello World!'

測定結果

実際、1000回のリクエストを行い、そのレスポンス時間を測った結果をグラフにして見ると、傾向は先頭の処理で1秒を超える結果がどのランタイムで発生している。

下記に取得したデータを元にスタッツを取得してみました。これをみてもあまり大きく変わらないことがわかりました。

go1.11go1.13Node.js 8Node.js 10Python3.7
最大値(sec)1.3339482.0697572.6836682.3100493.415535
最小値(sec)0.2102430.2095210.2107790.2103080.21056
平均値(sec)0.255959080.255406920.259132970.25702130.26209552
標準偏差0.062936140.097478720.104199650.114406530.15842786
1秒以上のデータ数13333

まとめ

今回は、メモリを256MiBという制約の元に色々なランタイムでほぼ同一条件のプログラムを作成し、性能を測ってみました。このメモリサイズではどのランライムでも大きな性能な違いは見られませんでした。Googleのドキュメントには、メモリを増やせばCPU割当も増えるとのことなので、処理速度を上げたければ、メモリを増やして欲しいとのことのようですね。

https://cloud.google.com/functions/pricing#compute_time