Y

ISUCON11予選参加

結果

ISUCON11予選に、チーム「z」(メンバーは私のみ)で参加しました。

結果は、23,886点 195位 (全598チーム) でした。[1]

ほとんど何もできずに終わりましたが、楽しかったです。

来年に向けて1年間準備します!

振り返り

Keep

  • 準備していたことはできた (mysqldumpslow設定, ALP設定など)

Problem

  • 準備不足 (ISUCON慣れしていない)
  • アプリ側何もできなかった (N+1問題すら解決できなかった)

Try

  • ISUCON11予選再実行
  • ISUCON過去問全部やる (ISUCON10予選問題しかやってない)
  • Go言語アプリに慣れる

当日やったこと

目次

  1. 初期ベンチ確認 (10:15)
  2. 準備作業 (10:45)
  3. 対応1 INDEX追加(timestamp) (11:15)
  4. 対応2 INDEX追加(jia_isu_uuid) (12:15)
  5. 対応3 サーバー2台利用(WEB+DB) (13:15)
  6. 対応4 DBログ書き込みのタイミングを変更 (14:15)
  7. 対応5 N+1解決失敗1 (14:30)
  8. 仕様再確認 (15:00)
  9. 対応6 /assets/以下をキャッシュ対象に設定 (16:00)
  10. 対応7 N+1解決失敗2 (17:00)

初期ベンチ確認 (10:15)

初期ベンチを実行。(3,278)

画面を見るためにhostsファイルを変更 (マニュアルに画面を見る方法が記載されていた)

sudo vi /etc/hosts

xxx.xxx.xxx.xxx isucondition.t.isucon.dev

準備作業 (10:45)

マニュアルを30分ぐらい読んだ。ISUの登録がエラーになり、最後まで理由が分からなかった。

ISUCON10予選の「isuumo」よりも構成が複雑と思った。(JIA? ISUからコンディションが送信される? どういう意味?)

とりあえずtopコマンド実行。以下を確認。

  • CPUは2コアあり、全体で100%近く利用されている
  • mysqldのCPU使用率が高い

f:id:yzono:20210828131500p:plain

f:id:yzono:20210828131529p:plain

  • gitコミット
cd /etc/
git init
git add .
git commit -a -m "Initial checkin."

cd /home/isucon/webapp/
git init
git add .
git commit -a -m "Initial checkin."
  • mysqldumpslow設定
sudo vi /etc/mysql/conf.d/my.cnf 

slow_query_log      = 1
slow_query_log_file = /var/lib/mysql/slow.log
long_query_time     = 0

sudo rm /var/lib/mysql/slow.log && sudo /etc/init.d/mysql restart
  • mysqldumpで使うコマンド
// 実行時間の合計が多い順でソート
mysqldumpslow -s t /var/lib/mysql/slow.log | head -30

// 平均実行時間が多い順でソート
mysqldumpslow -s at /var/lib/mysql/slow.log | head -30

// スロークエリログとして検出された件数で多い順でソート
mysqldumpslow -s c /var/lib/mysql/slow.log | head -30
  • DBバージョン確認
isucon@ip-192-168-0-11:~/webapp$ mysql --version
mysql  Ver 15.1 Distrib 10.3.31-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2

MariaDBMySQL のバージョン比較 [2]

f:id:yzono:20210828131818p:plain

  • ALP設定 [3]
wget https://github.com/tkuchiki/alp/releases/download/v0.3.1/alp_linux_amd64.zip
unzip alp_linux_amd64.zip
sudo install ./alp /usr/local/bin

sudo vim /etc/nginx/nginx.conf

http {
  log_format ltsv "time:$time_local"
    "\thost:$remote_addr"
    "\tforwardedfor:$http_x_forwarded_for"
    "\treq:$request"
    "\tmethod:$request_method"
    "\turi:$request_uri"
    "\tstatus:$status"
    "\tsize:$body_bytes_sent"
    "\treferer:$http_referer"
    "\tua:$http_user_agent"
    "\treqtime:$request_time"
    "\truntime:$upstream_http_x_runtime"
    "\tapptime:$upstream_response_time"
    "\tcache:$upstream_http_x_cache"
    "\tvhost:$host";

  access_log  /var/log/nginx/access.log ltsv;
}

sudo rm /var/log/nginx/access.log && sudo /etc/init.d/nginx restart
  • ALPで使うコマンド
alp -f /var/log/nginx/access.log | head
alp -r -f /var/log/nginx/access.log | head
alp --sum -r -f /var/log/nginx/access.log | head
alp --sum -r -f /var/log/nginx/access.log --aggregates='/api/condition/.*' | head
alp --sum -r -f /var/log/nginx/access.log --aggregates='/api/isu/.*' | head

対応1 INDEX追加(timestamp) (11:15)

  • 実行時間の合計が多いクエリ
sudo mysqldumpslow -s t /var/lib/mysql/slow.log | head -30

Count: 6482  Time=0.14s (889s)  Lock=0.00s (0s)  Rows_sent=1.0 (6343), Rows_examined=41212.3 (267137976), Rows_affected=0.0 (0), isucon[isucon]@localhost
  SELECT * FROM `isu_condition` WHERE `jia_isu_uuid` = 'S' ORDER BY `timestamp` DESC LIMIT N
  • 実行時間の合計が多いクエリのEXPLAIN
MariaDB [isucondition]> EXPLAIN SELECT * FROM `isu_condition` WHERE `jia_isu_uuid` = 'S' ORDER BY `timestamp` DESC LIMIT 10;
+------+-------------+---------------+------+---------------+------+---------+------+-------+-----------------------------+
| id   | select_type | table         | type | possible_keys | key  | key_len | ref  | rows  | Extra                       |
+------+-------------+---------------+------+---------------+------+---------+------+-------+-----------------------------+
|    1 | SIMPLE      | isu_condition | ALL  | NULL          | NULL | NULL    | NULL | 72591 | Using where; Using filesort |
+------+-------------+---------------+------+---------------+------+---------+------+-------+-----------------------------+
  • インデックス追加

jia_isu_uuidとtimestampのどちらに設定すべきか迷ったけど、カーディナリティが高い(であろう)timestampに設定した。どのカラムに設定すべきかはよく分かっていない。

CREATE INDEX idx_timestamp ON  isucondition.isu_condition(timestamp);
  • 実行時間の合計が多いクエリ (インデックス追加後)
Count: 3780  Time=0.06s (208s)  Lock=0.00s (0s)  Rows_sent=207.6 (784729), Rows_examined=15865.0 (59969855), Rows_affected=0.0 (0), isucon[isucon]@localhost
  SELECT * FROM `isu_condition` WHERE `jia_isu_uuid` = 'S' ORDER BY timestamp DESC

0.14s → 0.06s の改善

  • 実行時間の合計が多いクエリのEXPLAIN (インデックス追加後)
MariaDB [isucondition]> EXPLAIN SELECT * FROM `isu_condition` WHERE `jia_isu_uuid` = 'S' ORDER BY `timestamp` DESC LIMIT 10;
+------+-------------+---------------+-------+---------------+---------------+---------+------+------+-------------+
| id   | select_type | table         | type  | possible_keys | key           | key_len | ref  | rows | Extra       |
+------+-------------+---------------+-------+---------------+---------------+---------+------+------+-------------+
|    1 | SIMPLE      | isu_condition | index | NULL          | idx_timestamp | 5       | NULL |   10 | Using where |
+------+-------------+---------------+-------+---------------+---------------+---------+------+------+-------------+

72591 → 10 の改善

  • ベンチ実行

3,278 → 5,166 の改善

対応2 INDEX(jia_isu_uuid)追加 (12:15)

  • 実行時間の合計が多いクエリ
Count: 750  Time=0.16s (118s)  Lock=0.00s (0s)  Rows_sent=396.1 (297053), Rows_examined=36562.2 (27421666), Rows_affected=0.0 (0), isucon[isucon]@localhost
  SELECT * FROM `isu_condition` WHERE `jia_isu_uuid` = 'S'  AND `timestamp` < 'S'    ORDER BY `timestamp` DESC
  • 実行時間の合計が多いクエリのEXPLAIN
MariaDB [isucondition]> EXPLAIN SELECT * FROM `isu_condition` WHERE `jia_isu_uuid` = 'S'  AND `timestamp` < 'S'  ORDER BY `timestamp` DESC;
+------+-------------+---------------+------+---------------+------+---------+------+-------+-----------------------------+
| id   | select_type | table         | type | possible_keys | key  | key_len | ref  | rows  | Extra                       |
+------+-------------+---------------+------+---------------+------+---------+------+-------+-----------------------------+
|    1 | SIMPLE      | isu_condition | ALL  | idx_timestamp | NULL | NULL    | NULL | 73244 | Using where; Using filesort |
+------+-------------+---------------+------+---------------+------+---------+------+-------+-----------------------------+
  • インデックス追加

CREATE INDEX idx_jia_isu_uuid ON isucondition.isu_condition(jia_isu_uuid);

  • 実行時間の合計が多いクエリ (インデックス追加後)
Count: 2383  Time=0.02s (39s)  Lock=0.00s (0s)  Rows_sent=489.3 (1166055), Rows_examined=1174.4 (2798517), Rows_affected=0.0 (0), isucon[isucon]@localhost
  SELECT * FROM `isu_condition` WHERE `jia_isu_uuid` = 'S'  AND `timestamp` < 'S'    ORDER BY `timestamp` DESC

0.16s → 0.02s の改善

  • 実行時間の合計が多いクエリのEXPLAIN (インデックス追加後)
MariaDB [isucondition]> EXPLAIN SELECT * FROM `isu_condition` WHERE `jia_isu_uuid` = 'S'  AND `timestamp` < 'S'  ORDER BY `timestamp` DESC;
+------+-------------+---------------+------+--------------------------------+------------------+---------+-------+------+----------------------------------------------------+
| id   | select_type | table         | type | possible_keys                  | key              | key_len | ref   | rows | Extra                                              |
+------+-------------+---------------+------+--------------------------------+------------------+---------+-------+------+----------------------------------------------------+
|    1 | SIMPLE      | isu_condition | ref  | idx_timestamp,idx_jia_isu_uuid | idx_jia_isu_uuid | 144     | const |    1 | Using index condition; Using where; Using filesort |
+------+-------------+---------------+------+--------------------------------+------------------+---------+-------+------+----------------------------------------------------+

73244 → 1 の改善

  • ベンチ実行

5,166 → 15,894 の改善

対応3 サーバー2台利用(WEB+DB) (13:15)

  • WEB→DBへのアクセス許可設定
MariaDB [(none)]> SHOW GLOBAL VARIABLES like 'bind_address';
+---------------+-----------+
| Variable_name | Value     |
+---------------+-----------+
| bind_address  | 127.0.0.1 |
+---------------+-----------+
sudo vi /etc/mysql/mariadb.conf.d/50-server.cnf

#bind-address            = 127.0.0.1

sudo rm /var/lib/mysql/slow.log && sudo /etc/init.d/mysql restart
  • WEB→DBへのアクセス許可設定 (変更後)
MariaDB [(none)]> SHOW GLOBAL VARIABLES like 'bind_address';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| bind_address  | *     |
+---------------+-------+
  • isuconditionのサービス確認
$ cat /etc/systemd/system/isucondition.go.service

EnvironmentFile=/home/isucon/env.sh
  • env.shファイル変更
$ vi env.sh
MYSQL_HOST="xxx.xxx.xxx.xxx"

$ sudo /etc/init.d/isucondition.go.service restart
  • ベンチ実行

15,894 → 23,436 の改善

f:id:yzono:20210828131947p:plain

この時点で50位でした。

対応4 DBログ書き込みのタイミングを変更 (14:15)

  • 実行時間の合計が多いクエリ
Count: 10025  Time=0.00s (37s)  Lock=0.00s (0s)  Rows_sent=0.0 (0), Rows_examined=0.0 (0), Rows_affected=0.0 (0), isucon[isucon]@isucondition-1.t.isucon.dev
  COMMIT

この「COMMIT」の総時間が多かったので、DBログ書き込みのタイミングを変更しました。[4]

  • DBログ書き込みのタイミングを変更
$ sudo vi /etc/mysql/conf.d/my.cnf 

innodb_flush_log_at_trx_commit=2
  • 実行時間の合計が多いクエリ
Count: 9990  Time=0.00s (2s)  Lock=0.00s (0s)  Rows_sent=0.0 (0), Rows_examined=0.0 (0), Rows_affected=0.0 (0), isucon[isucon]@isucondition-1.t.isucon.dev
  COMMIT

37s → 2s の改善

  • ベンチ実行

23,436 → 23,196。ほぼ変化なし

  • topコマンド確認

f:id:yzono:20210828132205p:plain

f:id:yzono:20210828132252p:plain

DBの使用率は70%程度だったので、アプリ側の対応に着手しました。

対応5 N+1解決失敗1 (14:30)

  • ALPコマンド確認

f:id:yzono:20210828132103p:plain

1079 func getTrend(c echo.Context) error {
1080         characterList := []Isu{}
1081         err := db.Select(&characterList, "SELECT `character` FROM `isu` GROUP BY `character`")

N+1が発生していることを確認

  • スロークエリログとして検出された件数で多いクエリ確認
sudo mysqldumpslow -s c /var/lib/mysql/slow.log | head -30

Count: 25255  Time=0.00s (88s)  Lock=0.00s (0s)  Rows_sent=318.9 (8053234), Rows_examined=631.8 (15955566), Rows_affected=0.0 (0), isucon[isucon]@isucondition-1.t.isucon.dev
  SELECT * FROM `isu_condition` WHERE `jia_isu_uuid` = 'S' ORDER BY timestamp DESC

88sを解決できないか確認

all: isucondition

isucondition: *.go
    go build -o isucondition
  • 断念

クエリを1つにした場合にベンチエラーが発生したので一旦断念。

仕様再確認 (15:00)

アプリの仕様を理解するために、再度マニュアルや画面を確認しました。

  • ISU登録失敗
{"time":"2021-08-21T15:53:41.260291827+09:00","level":"ERROR","prefix":"echo","file":"main.go","line":"610","message":"failed to request to JIAService: Post \"http://13.113.232.243:5000/api/activate\": dial tcp 13.113.232.243:5000: connect: connection refused"}

{"time":"2021-08-21T15:53:41.260559356+09:00","id":"","remote_ip":"127.0.0.1","host":"isucondition.t.isucon.dev","method":"POST","uri":"/api/isu","user_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36","status":500,"error":"","latency":2877574,"latency_human":"2.877574ms","bytes_in":275,"bytes_out":0}

{"time":"2021-08-21T16:22:33.295717404+09:00","level":"ERROR","prefix":"echo","file":"main.go","line":"610","message":"failed to request to JIAService: Post \"/api/activate\": unsupported protocol scheme \"\""}

結局、最後までISU登録は成功しませんでした。

対応6 /assets/以下をキャッシュ対象に設定 (16:00)

isuconditionアプリログを見ると、/assets/へのアクセスが多かったのでキャッシュ設定を追加。[5]

  • WEBサーバー設定変更
server {
    location /assets/ {
        expires 24h;
    }
  • ベンチ実行

23,196 → 23,528。ほぼ変化なし

対応7 N+1解決失敗2 (17:00)

N+1問題に再チャレンジ。「時系列の最新を取得する」といえば「ウィンドウ関数」ではないか? MariaDBのバージョンも「ウィンドウ関数」をサポートしている。ということで試してみました。

  • ウィンドウ関数の結果
SELECT 
  i.id, 
  i.jia_isu_uuid, 
  c.condition, 
  c.timestamp 
FROM   
  isu i 
INNER JOIN
(
SELECT 
  c.id,
  c.condition, 
  c.timestamp,
  Row_number() OVER ( 
    partition BY 
      id 
    ORDER BY 
      timestamp DESC 
  ) AS seqnum 
FROM   
    `isu_condition` c
) c
WHERE
  i.id = c.id
AND
  c.seqnum = 1;

+----+--------------------------------------+----------------------------------------------------+---------------------+
| id | jia_isu_uuid                         | condition                                          | timestamp           |
+----+--------------------------------------+----------------------------------------------------+---------------------+
| 14 | 023c8e56-4410-484d-b7fa-702d48188d3c | is_dirty=false,is_overweight=false,is_broken=false | 2021-06-04 04:59:09 |
| 21 | 0634a999-5f5b-4e8b-bee6-f95d622954a4 | is_dirty=true,is_overweight=false,is_broken=false  | 2021-06-04 11:59:09 |
| 63 | 063a0168-f0da-4603-9267-4f05c8565c45 | is_dirty=false,is_overweight=false,is_broken=true  | 2021-06-06 05:59:09 |
| 23 | 08985a64-c425-48d2-ac33-25ac61d5a931 | is_dirty=false,is_overweight=false,is_broken=false | 2021-06-04 13:59:09 |
| 24 | 0b675a72-c8fd-4c21-b87b-eefc1d5df5e4 | is_dirty=false,is_overweight=true,is_broken=false  | 2021-06-04 14:59:09 |
| 34 | 0bb7ebac-2dd0-49c8-a3bf-830a5b3c02a1 | is_dirty=false,is_overweight=true,is_broken=false  | 2021-06-05 00:59:09 |
| 65 | 1135cbe0-c5f5-4e77-ac87-d79dce97b1a7 | is_dirty=false,is_overweight=false,is_broken=true  | 2021-06-06 07:59:09 |
|  4 | 15063e10-26fc-4dac-ae3a-1f195e0c6c4a | is_dirty=true,is_overweight=false,is_broken=true   | 2021-06-03 18:59:09 |

当時は「それっぽい結果が出た」と思いました。

  • ベンチ実行

失敗。時間が迫っていたのでソースコードを元に戻しました。

最終作業 (18:00)

各サーバーを再起動してベンチを実行して、結果が問題ないことを確認しました。

参考

[1] ISUCON11 オンライン予選 全てのチームのスコア(参考値) https://isucon.net/archives/56021246.html

[2] MariaDBMySQL のバージョン比較 https://qiita.com/katzueno/items/e735950c7440f232ef27

[3] alpのインストールからNginxのアクセスログ解析までの手順【ISUCON】 https://nishinatoshiharu.com/install-alp-to-nginx/

[4] [ISUCON用メモ] MySQL https://qiita.com/stomk/items/6265e9fdfdfb4f104a7e

[5] nginxで静的コンテンツをキャッシュ配信する方法 https://nishinatoshiharu.com/nginx-static-deliver/

ISUCON11予選準備

準備したこと

8/21 ISUCON11予選に向けて、ISUCON10予選を試してみました。 具体的に対応した結果とスコアは以下です。

  1. 初期スコア (444)
  2. ChairテーブルINDEX(500)
  3. EstateテーブルINDEX(531)
  4. MySQL8アップグレード (308)
  5. 降順INDEX(601)
  6. N+1問題 (628)
  7. 空間INDEX (645)
  8. bot削除 (1126)
  9. gzip圧縮の有効 (1060)
  10. WEB+DB構成 (1340)
  11. DB複数台構成 (x)
  12. New Relic (x)

資料

準備の詳細は下記資料にまとめました。

IBM Cloudライト・アカウントでサポートケースを発行する

質問内容とサポートセンター

前回の記事でIBM Cloudライト・アカウントの利用制限(1ヶ月あたり1,000リクエスト)を超えたのに、制限エラーが発生しなかった件について、サポートに問い合わせます。

サポートセンターのページを見ると、ライトアカウントでも料金や利用数については、サポートケースを発行できるようです。ただし、技術的なサポートはライトアカウントではできないようです。

Support cases for Lite accounts As a Lite account user, you can create a case for any account, access, or billing and usage issue. If you want to create a case for technical support, upgrade your account

https://cloud.ibm.com/unifiedsupport/cases/form

サポートケース発行方法

1.サポートサイトにアクセスして、Billing and usageをクリック

https://cloud.ibm.com/unifiedsupport/cases/form

f:id:yzono:20201112112801p:plain

2.サービス使用量の詳細の表示をクリック

f:id:yzono:20201112112823p:plain

3.「管理」>「請求および使用量」に移動し、「使用量」を選択

f:id:yzono:20201112112842p:plain

4.使用量の表示をクリック

f:id:yzono:20201112112903p:plain

5.プランの表示をクリック

f:id:yzono:20201112112920p:plain

6.詳細を表示をクリック、数量が1,000を超えていることを確認

f:id:yzono:20201112112941p:plain

7.2に戻り、ケース内容を入力

f:id:yzono:20201112113004p:plain

8.確認画面でSubmitをクリック

f:id:yzono:20201112113102p:plain

9.ケースが作成されていることを確認

f:id:yzono:20201112113144p:plain

IBM Cloudライト・アカウントの利用制限

IBM Cloudライト・アカウントの料金プラン

IBM Cloudライト・アカウントの料金プランでは、1ヶ月あたり1,000個の事前トレーニング済みモデルの分類 (一般、食品、明示的)は無料です。

Watson Visual Recognition - 料金設定 - 日本 | IBM

本記事では、その上限を超えるリクエストを実行した場合の挙動を確認します。尚、必要なAPIキーの取得方法などは過去の記事を参照してください。

上限を超えるリクエストの実行方法

1.秒間リクエスト可能数を確認する

1秒間にアクセス可能なAPI数は料金表に明示されていないため、秒間10リクエスト程度を試したところエラーは発生しませんでした。

2.1,000件を超えるのリクエストを実行する

$ for ((i=1;i<=1000;i++)); do time curl -u "apikey:XXX" "https://api.kr-seo.visual-recognition.watson.cloud.ibm.com/instances/XXX/v3/classify?url=https://watson-developer-cloud.github.io/doc-tutorial-downloads/visual-recognition/fruitbowl.jpg&version=2018-03-19"; done

上記を実行した結果、エラーは発生しませんでした。件数の反映には時間がかかるのかもしれません。時間をおいて試してみます。

IBM Cloud Visual Recognition を試す

IBM Cloud Visual Recognitionとは

Watson Visual Recognitionは、企業などの組織が持つ画像から数千のラベルを抽出したり、特定のコンテンツを検知することができます。アプリケーションの中に、画像から特定のコンテンツを検知するためのカスタムモデルを構築することも可能です。

Watson Visual Recognition - 概要 - 日本 | IBM

Azure Face APIは顔の情報を検知しましたが、Watson Visual Recognitionは、画像内の物体の分類ができるようです。

IBM Cloud Visual Recognition を試す (デモサイト)

1. Watson Visual Recognitionにアクセスして、デモサイト(英語)をクリック

Watson Visual Recognition - 概要 - 日本 | IBM

f:id:yzono:20201110012412p:plain

2. 画面を選択すると結果が下に表示される

f:id:yzono:20201110012433p:plain

IBM Cloud Visual Recognition を試す (API)

1. リソースリストからVisual Recognitionをクリック

https://cloud.ibm.com/resources

f:id:yzono:20201110012511p:plain

2. API鍵とURLをコピー

f:id:yzono:20201110012627p:plain

3. リクエスト実行

$ curl -u "apikey:XXX" "https://api.kr-seo.visual-recognition.watson.cloud.ibm.com/instances/XXX/v3/classify?url=https://watson-developer-cloud.github.io/doc-tutorial-downloads/visual-recognition/fruitbowl.jpg&version=2018-03-19"
{
    "images": [
        {
            "classifiers": [
                {
                    "classifier_id": "default",
                    "name": "default",
                    "classes": [
                        {
                            "class": "banana",
                            "score": 0.562,
                            "type_hierarchy": "/fruit/banana"
                        },
                        {
                            "class": "fruit",
                            "score": 0.788
                        },
                        {
                            "class": "diet (food)",
                            "score": 0.528,
                            "type_hierarchy": "/food/diet (food)"
                        },
                        {
                            "class": "food",
                            "score": 0.528
                        },
                        {
                            "class": "honeydew",
                            "score": 0.5,
                            "type_hierarchy": "/fruit/melon/honeydew"
                        },
                        {
                            "class": "melon",
                            "score": 0.501
                        },
                        {
                            "class": "olive color",
                            "score": 0.973
                        },
                        {
                            "class": "lemon yellow color",
                            "score": 0.789
                        }
                    ]
                }
            ],
            "source_url": "https://watson-developer-cloud.github.io/doc-tutorial-downloads/visual-recognition/fruitbowl.jpg",
            "resolved_url": "https://watson-developer-cloud.github.io/doc-tutorial-downloads/visual-recognition/fruitbowl.jpg"
        }
    ],
    "images_processed": 1,
    "custom_classes": 0
}

Azure Face API 有料インスタンスに変更する方法

Face APIの料金体系

https://azure.microsoft.com/ja-jp/pricing/details/cognitive-services/face-api/:title

インスタンスタイプが以下2つあります。

1.Free - Web/コンテナー

2.Standard - Web/コンテナー

「2.Standard - Web/コンテナー」を選択している場合は、APIの呼び出しに対して費用がかかります。

本日時点の価格は以下のとおりであり、トランザクション数が多くなる毎に単価が下がります。

0 ~ 1M のトランザクション - ¥112/1,000 トランザクション
1M ~ 5M のトランザクション - ¥89.600/1,000 トランザクション
5M ~ 100M のトランザクション - ¥67.20/1,000 トランザクション
100M 以上のトランザクション - ¥44.800/1,000 トランザクション

尚、1 秒あたりのトランザクション数 (TPS) は、10TPSとなっており、一定の制限があります。

本記事では、インスタンスタイプの変更方法と変更後に1分間に20件以上のリクエストが実行することができるかを確認します。

インスタンスタイプの変更方法

1.Azureポータルを開き、すべてのリソースをクリック

Microsoft Azure

f:id:yzono:20201108183230p:plain

2.対象インスタンスをクリック

f:id:yzono:20201108183302p:plain

3.価格レベルをクリック

f:id:yzono:20201108183326p:plain

4.F0 Standardを選択して、選択ボタンクリック

f:id:yzono:20201108190624p:plain

5.1分間に20回以上のトランザクションを実行する

for ((i=1;i<=25;i++)); do sleep 1; time curl -X POST -H "Ocp-Apim-Subscription-Key: XXX" -H "Content-Type: application/json" -d '{"url": "https://azurecomcdn.azureedge.net/cvt-9281d9db0c63a479d39019e02b1bc35d712622992174d8bb4dcb33f728511a17/images/shared/cognitive-services-demos/face-detection/detection-1-thumbnail.jpg"}' "https://dev-inst-cog-faced.cognitiveservices.azure.com/face/v1.0/detect?returnFaceId=true&returnFaceLandmarks=false&recognitionModel=recognition_03&returnRecognitionModel=false&detectionModel=detection_02"; done


[{"faceId":"2d2274f1-9af4-4f74-b82f-26570d5cb42b","faceRectangle":{"top":22,"left":62,"width":71,"height":87}}]
real    0m0.069s
user    0m0.018s
sys 0m0.006s

想定どおり20回を超えた場合でもエラーは発生しませんでした。

f:id:yzono:20201108191455p:plain

尚、上記のとおり25件分のリクエストに対する課金額については表示されませんでした。表示までに一定の時間がかかると思われます。

翌日金額反映

翌日に確認したところ、想定していた金額が反映されていました。約1,000件リクエストを実行した結果、114円コストがかかっています。リクエスト数は表示されないようです。

表示オプション「グループ化(Billing Periodなど)」、「細分性(累積、日単位、月単位)」、「グラフ種別(領域、テーブルなど)」により、様々な表示が可能です。

f:id:yzono:20201110002517p:plain

Azure Face API Freeインスタンスの制限について

Face APIの料金体系

https://azure.microsoft.com/ja-jp/pricing/details/cognitive-services/face-api/:title

インスタンスタイプが以下2つあります。

1.Free - Web/コンテナー

2.Standard - Web/コンテナー

「1.Free - Web/コンテナー」を選択している場合は、利用制限があり、制限以上のトランザクションはエラーが発生します。

利用制限は以下のとおりです。

  • 1分間(60秒)にコールできるAPI数 = 20件 (3秒に1回コールできる)

  • 30000件(1ヶ月の最大) / 20件(1分間の最大) = 1500分(1分間中の制限の上限を利用した場合の、最大継続時間) = 25時間

トランザクションの説明は上記サイトに記載されています。

100 万単位でのトレーニングが可能な操作 (2018 年 3 月 1 日から利用可能) の場合、トレーニングした画像 1,000 個ごとに 1 トランザクションとしてカウントされます。"LargePersonGroup - Train" と "LargeFaceList - Train" はこのカテゴリに属します。このカテゴリの各操作では、画像の数が最も近い 1,000 個単位に丸められます。たとえば、849,500 個の画像を含む "LargeFaceList - Train" 操作は 850 トランザクションとしてカウントされます。他のすべての操作では、API 呼び出しごとに 1 トランザクションとしてカウントされます。

本記事では、「1.Free - Web/コンテナー」を選択した状態で、制限以上のトランザクションを実行した場合の挙動を見てみます。

制限以上のトランザクションの実行方法

1.Azureポータルを開き、すべてのリソースをクリック

Microsoft Azure

f:id:yzono:20201108183230p:plain

2.対象インスタンスをクリック

f:id:yzono:20201108183302p:plain

3.価格レベルをクリック

f:id:yzono:20201108183326p:plain

4.F0 Freeが選択されていることを確認

f:id:yzono:20201108183353p:plain

5.1分間に20回以上のトランザクションを実行する

for ((i=1;i<=25;i++)); do sleep 1; time curl -X POST -H "Ocp-Apim-Subscription-Key: XXX" -H "Content-Type: application/json" -d '{"url": "https://azurecomcdn.azureedge.net/cvt-9281d9db0c63a479d39019e02b1bc35d712622992174d8bb4dcb33f728511a17/images/shared/cognitive-services-demos/face-detection/detection-1-thumbnail.jpg"}' "https://dev-inst-cog-faced.cognitiveservices.azure.com/face/v1.0/detect?returnFaceId=true&returnFaceLandmarks=false&recognitionModel=recognition_03&returnRecognitionModel=false&detectionModel=detection_02"; done


[{"faceId":"2d2274f1-9af4-4f74-b82f-26570d5cb42b","faceRectangle":{"top":22,"left":62,"width":71,"height":87}}]
real    0m0.069s
user    0m0.018s
sys 0m0.006s

{"error":{"code":"429","message": "Requests to the Face - Detect Operation under Face API - v1.0 have exceeded rate limit of your current Face F0 pricing tier. Please retry after 30 seconds. To increase your rate limit switch to a paid tier."}}
real    0m0.093s
user    0m0.020s
sys 0m0.008s

想定どおり20回を超えた場合に制限超えのメッセージが表示される。