[Cloudflare Workers]CPU実行時間を計測する[実験]

# はじめに
Cloudflare Workers使ってみてるのですが、無料枠だとCPU実行時間が10msという制限があり、実用に耐えうるレベルなのか計測してみました。

一応ドキュメントには、ほとんどのリクエストは1ms以下だし、10ms超えるのは稀だと書いてあるのですが、自分が作成したアプリだと普通に超えちゃったので何がそんなにCPU実行時間を使っているのか確認するのが目的です。

補足ですが、CPU実行時間は外部APIの待機とかは含まれず、純粋にCPUを使っている時間ということなのですが、個別のリクエストに対して計測する方法がないので、Cloudflareのコンソールで見ることができる以下のような中央値で計測します。デプロイごとの中央値を確認できるので、ある条件でリクエストしたら再度デプロイして計測しなおします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/d2e1d3d5-6832-4c07-2ecf-ee89320fcad9.png)

調べようと思えばある程度は調べられるんですが、サーバー自体にアクセスできるわけでもないのでこれが一番正確かなと思います。

フレームワークはHono、ORMはdrizzleを使い、同様のリクエストを10回前後送って中央値を確認します。

※ middlewareや使っているライブラリやエンドポイントの数でこちらの値は変わる可能性もあるので、あくまで参考値として考えてください。

# シンプルなテキストを返すだけのエンドポイント

```typescript
app.get('/', (c) => c.text('Hono!!'));
```

キャッシュが効く可能性も考慮して、一応クエリパラメータを変えてリクエストしました。

この場合の結果が、最初の例として添付したこちらです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/d2e1d3d5-6832-4c07-2ecf-ee89320fcad9.png)


# 1回UPDATEが実行されるエンドポイント
以下のように1つのリソースのupdateを行うだけのエンドポイントです。
```typescript
const db = drizzle(c.env.productionDB);
await db
      .update(users)
      .set({ name: params.name })
      .where(eq(users.id, params.id));

return c.json('ok', 201);
```




中央値はこちらです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/b04fd11e-6c70-fd91-0328-4913c3475497.png)

こちらの中間値はクエリを10回実行したものなので、もう5回くらい実行してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/1e168631-4974-c4f3-12b3-a6dfad565616.png)

多少ばらつきがあるのかもしれません。

一応さらに5回実行しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/6f810687-c2bb-26f9-b350-b99404ce05a5.png)

何かしらメモリに残ってたりして回数重ねると、ある程度は早くなるのかもしれません。
単純計算だと、1回のクエリを実行すると0.7msかかるっていうことですかね。

ただし、クエリのやりとりで時間かかっているのか、drizzleの初期化に時間かかっているかわからないので、updateクエリをもう一つ追加してみます。

# 2回UPDATEが実行されるエンドポイント
```typescript
const client = drizzle(c.env.productionDB);

await client
  .update(users)
  .set({ name: params.name })
  .where(eq(users.uid, params.id));

await client
  .update(users)
  .set({ name: 'name' })
  .where(eq(users.uid, params.id));

return c.json('ok', 201);
```
あまり意味あるクエリではありませんが、20リクエスト送った結果は以下です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/e23f5bdd-dc10-bab5-abb2-ae6fb811c200.png)

この結果から鑑みるに、1クエリの場合との差分が0.3msなので、1クエリで大体0.3msくらいを使うイメージでしょうか。

# 補足
リクエストを送れば送るほど中間値が小さくなるため、実際どの程度中間値が変わるのか試してみました。
以下の結果はupdateクエリを1回だけ実行したものです。

1回
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/75f2534b-0b3c-8f33-4302-71fa41b8e109.png)

3回
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/49fdaad8-5036-d25a-eb02-9a72f9e7f882.png)

5回
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/0fd160b3-b204-5ee3-f5f1-a3b09e65274e.png)

6回
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/666ebacd-0a58-ee80-b891-1df82f394b32.png)

7回
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/a2cc367a-c4d8-efb3-bba8-4f902193a681.png)

10回
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/e8b00182-a5d4-1bf9-8c17-77324ff41ac8.png)

10回に関して先ほどの結果と異なるのですが、これはコンソールに値が反映されるのに時間がかかるため、時間をおいてリクエストを送ったためと思います。
一気に10回リクエストを送ると何かしらのキャッシュやら、メモリやらが残っていて、高速化されるのかもしれません。

# まとめ
データベースとのデータのやりとりが多少あるくらいなら10msは問題なさそうっていうことが分かりました。

とはいえ、自分の実装では外部APIを実行したり、多少複雑なことをしているためか10msを結構超えてしまいました。
ただ、中間値やmax値が10msを超えたからすぐに使えなくなるものでもなさそう（10ms超えていても問題なく使えてるという情報をどこかで見た）なので、そこまでシビアに考える必要はないと思いますが、無料枠なのでそこはご留意頂ければなと思います。

可能であればCloudflare側には1リクエストに対するCPU実行時間を確認する方法を実装して頂けると大変嬉しいですね。

最初の方にも記載しましたが、使っているライブラリやミドルウェアの実装によってこの辺の値は変わってくると思いますので、参考までにお願いします。