Cloudflareは、WorkersおよびDurable ObjectsサービスのCPUとメモリ使用量をオンデマンドでプロファイリングできるようにした。これにより開発者は、プロダクション環境そのものからプロファイルを収集し、インタラクティブなフレームグラフとして表示できる。この機能を使えば、集計ログや全体的な指標だけに頼ることなく、CPU時間を消費している関数や、より多くのメモリを割り当てている関数を特定できる。
プロファイリングは、CloudflareダッシュボードのWorkers Observabilityページ、またはコマンドラインインターフェースから実行できる。開発者はプロファイルの種類(CPUまたはmemory)と収集時間を指定し、異なるWorkerのバージョンを選択することもできる。セッション終了後は、インタラクティブなグラフを表示し、プロファイルファイルをダウンロードして他のツールで分析できる。
フレームグラフに表示される内容
グラフ内の各長方形は関数呼び出しを表し、その幅は関連付けられたCPU時間またはメモリ量を示す。関数をクリックしてフォーカスを拡大したり、表形式の表示でサンプル数に基づいて結果を並べ替えたりできる。Cloudflareは、複数のプロファイルを取得して幅の広い関数を探すことを推奨している。また、TypeScriptプロジェクトではsource mapsを有効にし、関数名が不明瞭に表示されないようにすることも推奨している。
プロファイリングには、十分なトラフィックを受けているデプロイ済みバージョンを選択する必要がある。このサービスは測定のために新たな分離環境を作成しない。目的は、プロダクションでの実際の実行を監視することだからだ。次のコマンドを使えば、5秒間のCPUプロファイルを取得できる。
cf workers versions profile latest --worker-id "$WORKER_ID_OR_NAME" --duration-ms 5000 --profile-type cpu > worker-cpu.pprof
Cloudflareが示した実用的な結果
Cloudflareは、R2バインディングを適用するWorkerの分析にこのツールを使用した。プロファイリングの結果、genericR2JsonReplacer関数がJSON.stringifyの実行中にJSONツリーを再走査しており、一部のケースではネストされた値を5回処理していることが判明した。これを修正した結果、関数は2.7倍高速になった。また、プロファイリングによってmetricsの重複呼び出しも明らかになり、結果を保存して再利用するだけでCPU使用量を削減できた。
別のケースでは、あるWorkerが128メガバイトのメモリ上限を超えており、P999の使用量が約133メガバイトに達したことで「Exceeded Memory」エラーが発生していた。ヒーププロファイルによると、割り当ての約66.7%を占めるPrometheusコードが、無効化されていると思われていたにもかかわらず、一部でまだ実行されていた。コードパス全体を削除した後、P999は133メガバイトから118メガバイトに低下し、P50も70メガバイトから54メガバイトに減少した。
実際に何が変わるのか
この機能により、開発チームは実際の条件下でのWorkersの実行を直接把握できる。トラフィックや分離環境の分布は、ローカルの開発環境とは異なる可能性がある。プラットフォームは、複数のデータセンターやデバイスにWorkersを分散させる複雑さを処理する。一方、Durable Objectsでは、開発者がオブジェクトを名前で指定し、特定のオブジェクトを実行している分離環境のプロファイルを取得できる。
実行の仕組みにより、収集中もリクエストの受信は継続される。分離環境のロックが保持されるのはプロファイリングの開始時と停止時だけで、その後、指定された期間中は1ミリ秒間隔でCPUサンプルが収集される。Durable Objectsでは、ステートフルな性質を活用して、プロファイリングリクエストを指定されたオブジェクトの分離環境および所有者に転送する。
制限と次のステップ
プロファイリングは自動的に開始されないため、障害が発生する短時間またはまれな期間をセッションが逃す可能性がある。また、メモリプロファイラーが表示するのは測定ウィンドウ中に発生した割り当てだけであり、起動時に生じた使用量を必ずしも捕捉できるとは限らない。Cloudflareは、サンプルを自動的に収集し、後からダッシュボードで閲覧できる継続的プロファイリングに取り組んでいると述べている。