0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DNSAdvent Calendar 2024

Day 1

DNSのスループット、ボクが測ってみた!

Last updated at Posted at 2024-11-30

➊ はじめに 🦌🛷🛷🛷🎁🎄

今年も 🔔聖なる季節🔔 がやってまいりました~!
みなさま、チキンDNSスループット計測 の準備はよろしいでしょうか?

「えっ?DNSスループット?DNSがそんなに重要なの?」って思うかもしれませんが、実はこれ、ウェブページの表示速度や、アプリのレスポンスに、密接に関わっているんです。

➋ 具体的に何をするか


DNS性能の重要指標のひとつに、1秒間に処理できるクエリ数(Queries Per Second: QPS)があります。この値が高ければ高いほど、DNSサーバーが多くのリクエストに対応できる状態を示します。

なぜQPSが重要なのか?
DNSはすべてのインターネット通信の玄関口です!例えば、ユーザーがウェブサイトを開く際には、必ずDNSリクエストが発生します。この速度が遅ければ、いくら回線が速くても全体のパフォーマンスに影響を及ぼします。

そんなDNS性能を簡単に測定できるツールが、dnsperf なんです 🤗

👉今回、テスト環境を構築して dnsperf を使い計測を行ったところ、面白い結果が出たので、その過程をシェアしたいと思います!

  • dnsperf : DNSスループットを計測するツール
  • gnuplot : データからグラフを作成するツール

➌ dnsperf と resperf

dnsperfというツール」をインストールすると、dnsperfに加えて、resperfというコマンドが使えるようになります。dnsperfresperfの違いは、動作目的とテスト方法にあります。

dnsperf コマンド resperf コマンド
目的 一定のクエリレートでDNSサーバーのスループットを測定する。 DNSサーバーがどれだけのクエリレートに耐えられるかを測定する(限界値を把握する)。
挙動 設定した固定の負荷でDNSクエリを送信し、スループットを測定します(一定負荷型)。 クエリの送信レートを徐々に増加させ、応答率やレイテンシをモニタリングすることで限界を評価します(負荷増加型)。
用途 DNSサーバーのスループットを確認し、一定負荷の環境での応答速度や安定性を評価する。 DNSサーバーのレイテンシや耐久力、ピークパフォーマンスを測定し、サーバーの負荷増加時の最大クエリ処理能力(最大QPS)やボトルネックの発見に使用される。

➍ 本記事で遊ぶために

本記事で遊ぶためには、以下のツールが必要です。コマンドを実行して、dnsperf(DNSクエリを送信するツール)とgnuplot(グラフを描くツール)をインストールしておいてください。

⬢ ツールインストール方法

dnsperfをインストールする準備(依存関係のライブラリ等をインストールしておきます)

Ubuntu
> sudo apt update
> sudo apt upgrade
> sudo apt install -y libssl-dev libldns-dev libck-dev libnghttp2-dev

dnsperf、gnuplotのインストール方法

Ubuntu
> sudo apt install dnsperf
> sudo apt install gnuplot

dnsperfのソースコードやインストールの詳細情報はこちらに情報があります。

⬢ サンプルDNSクエリ

実DNSクエリのサンプルはこちらにあります。ご参考まで。

🚨 警告 🐝➰
試験用の閉じたネットワークではなく、実ネットワークに繋げて、DNSクエリを巨大な量で送信すると、システムに負荷がかかる可能性が高いです。負荷試験については、十分気を付けてください。

サンプルクエリは圧縮(xzファイル)されているので、解凍して使います。解凍するには以下の「xz-utils」ツールが必要となります。

Ubuntu
> sudo apt install xz-utils

解凍は、xzコマンドを使用します。以下は解凍例です。

Ubuntu
> xz -d CompressedFile.xz

※DNSクエリを作成するツールも作ったのですが、ここでは割愛します🙁…

➎ コマンド概説

(1) dnsperf

dnsperf -hの内容を記載します。

Ubuntu
> dnsperf -h
DNS Performance Testing Tool
Version 2.14.0

Usage: dnsperf [-f family] [-m mode] [-s server_addr] [-p port]
               [-a local_addr] [-x local_port] [-d datafile] [-c clients]
               [-T threads] [-n maxruns] [-l timelimit] [-b buffer_size]
               [-t timeout] [-e] [-E code:value] [-D]
               [-y [alg:]name:secret] [-q num_queries] [-Q max_qps]
               [-S stats_interval] [-u] [-B] [-v] [-W] [-h] [-H] [-O]
  -f DNSトランスポートのアドレスファミリ、inet または inet6(デフォルト: any)
  -m トランスポートモードを設定:udp、tcp、dot(DNS over TLS)、または doh(DNS over HTTPS)(デフォルト: udp)
  -s クエリを送信するサーバー(デフォルト: 127.0.0.1)
  -p クエリを送信するサーバーのポート(デフォルト: udp/tcp 53、DoTは853、DoHは443)
  -a クエリを送信する際のローカルアドレス
  -x クエリを送信する際のローカルポート(デフォルト: 0)
  -d 入力データファイル(デフォルト: stdin)
  -c クライアント数
  -T 実行するスレッド数
  -n 入力を最大N回実行する
  -l 実行時間の上限(秒)
  -b ソケットの送受信バッファサイズ(キロバイト単位)
  -t クエリ完了のタイムアウト時間(秒)(デフォルト: 5)
  -e EDNS 0 を有効にする
  -E EDNSオプションを送信する
  -D DNSSEC OKビットをセットする(EDNSを前提とする)
  -y TSIG アルゴリズム、名前、シークレット(base64)
  -q 未処理クエリの最大数(デフォルト: 100)
  -Q 1秒あたりのクエリ数を制限する
  -S 1秒あたりのクエリ数(QPS)統計をN秒ごとに出力する
  -u クエリの代わりにダイナミックアップデートを送信する
  -B 入力ファイルをTCPストリームバイナリ形式として読み込む
  -v 詳細情報を標準出力に報告し、各クエリを表示する
  -W 警告やエラーを標準エラー出力ではなく標準出力にログする
  -h このヘルプを表示する
  -H 長いオプションヘルプを表示する
  -O 長いオプションを設定:<name>=<value>

⬢ コマンドサンプル

Ubuntu
> dnsperf -s "192.168.10.1" -d dns_queries.txt -q 1000 -Q 1000 -S 1 -l 60
  • -s "192.168.10.1" : DNSサーバの指定
  • -d dns_queries.txt : 送信するDNSクエリの指定(フォーマットはサンプルDNSクエリ参照
  • -q 1000 : 同時に送信できる未処理クエリの最大数を1000に設定
  • -Q 1000 : クエリ送信レートの上限を1000QPSに設定
  • -S 1 : 1秒あたりのクエリ数(QPS)統計を1秒ごとに出力
  • -l 60 : 実行時間の上限(60秒)

(2) resperf

resperf -hの内容を記載します。

Ubuntu
> resperf -h
DNS Resolution Performance Testing Tool
Version 2.14.0

Usage: resperf [-f family] [-M mode] [-s server_addr] [-p port]
               [-a local_addr] [-x local_port] [-d datafile] [-t timeout]
               [-b buffer_size] [-e] [-E code:value] [-D]
               [-y [alg:]name:secret] [-i plot_interval] [-m max_qps]
               [-P plotfile] [-r ramp_time] [-c constant_traffic_time]
               [-L max_query_loss] [-C clients] [-q num_outstanding] [-v]
               [-W] [-R] [-F fall_behind] [-h] [-H] [-O]
  -f DNSトランスポートのアドレスファミリ、inet または inet6(デフォルト: any)
  -M トランスポートモードを設定:udp、tcp、dot(DNS over TLS)、または doh(DNS over HTTPS)(デフォルト: udp)
  -s クエリを送信するサーバー(デフォルト: 127.0.0.1)
  -p クエリを送信するサーバーのポート(デフォルト: udp/tcp 53、DoTは853、DoHは443)
  -a クエリを送信する際のローカルアドレス
  -x クエリを送信する際のローカルポート(デフォルト: 0)
  -d 入力データファイル(デフォルト: stdin)
  -t クエリ完了のタイムアウト時間(秒)(デフォルト: 45)
  -b ソケットの送受信バッファサイズ(キロバイト単位)
  -e EDNS 0 を有効にする
  -E EDNS オプションを送信する
  -D DNSSEC OK ビットをセットする(EDNSを前提とする)
  -y TSIG アルゴリズム、名前、シークレット
  -i プロットデータポイント間の時間間隔(秒)(デフォルト: 0.5)
  -m 1秒あたりの最大クエリ数(デフォルト: 100000)
  -P プロットデータファイルの名前(デフォルト: resperf.gnuplot)
  -r ランプアップ時間(秒)(デフォルト: 60)
  -c 一定のトラフィックを送信する時間(秒)(デフォルト: 0)
  -L 許容できる最大クエリ損失率(パーセント)(デフォルト: 100)
  -C クライアント数(デフォルト: 1)
  -q 未処理クエリの最大数(デフォルト: 65536)
  -v 詳細情報を標準出力に報告する
  -W 警告やエラーを標準エラー出力ではなく標準出力にログする
  -R データファイルの再オープンを許可し、無限に使用可能にする
  -F 遅延が許容される最大クエリ数、0に設定すると無効化(デフォルト: 1000)
  -h このヘルプを表示する
  -H 長いオプションヘルプを表示する
  -O 長いオプションを設定:<name>=<value>

⬢ コマンドサンプル

Ubuntu
> resperf -s "192.168.10.1" -d dns_queries.txt -r 60 -m 1500 -P resperf_result.txt
  • -s "192.168.10.1" : DNSサーバの指定
  • -d dns_queries.txt : 送信するDNSクエリの指定(フォーマットはサンプルdnsクエリ参照
  • -r 60 : ランプアップ時間(60秒)
  • -m 1500 : 1秒あたりの最大クエリ数(1500クエリ)
  • -P resperf_result.txt : プロットデータファイルの名前

(3) gnuplot

gnuplot -hの内容を記載します。

Ubuntu
> gnuplot -h
Usage: gnuplot [OPTION] ... [FILE]
  -V, --version                バージョン情報を表示
  -h, --help                   ヘルプを表示
  -p, --persist                プロットウィンドウを開いたまま保持
  -s, --slow                   スローモードで実行
  -d, --default-settings       デフォルト設定を使用
  -c,                          スクリプトファイル ARG1 ARG2 ...
  -e,                          "コマンド1; コマンド2; ..."
gnuplot 5.4 パッチレベル 2

⬢ コマンドサンプル

Ubuntu
> gnuplot -p plot_dnsperf.gp
  • -p : プロットウィンドウを開いたまま保持
  • plot_dnsperf.gp : スクリプトファイルの指定

スクリプトファイルの中身については、実際の使用例を見た方が早いと思います。詳細は、gnuplot公式サイトでのご確認をお願いします。
👉️gnuplotの公式サイトはこちら

➏ dnsperf でグラフを作成

dnsperfの結果からグラフを作成するため、dnsperfresperfのコマンド用スクリプトと、gnuplotがグラフを作成するためのスクリプトを作成しておきましょう。

(1) 作図スクリプト(QPS)の準備

gnuplotで作図するための設定(スクリプト)です。

plot_dnsperf.gp
# plot_dnsperf.gp

set title "DNS Performance (dnsperf)"
set xlabel "Time (s)"
set ylabel "Queries per Second (qps)"
set xrange [0:60]       # x軸の範囲を 0 から 60 秒に設定
set yrange [0:1500]     # y軸の範囲を 0 から 1500 QPS に設定
set xtics 5             # x軸の目盛りの間隔を10に設定
set ytics 100           # y軸の目盛りの間隔を50に設定
set grid
set format y "%4.0f"    # 整数を4桁で表示
set encoding utf8
set terminal pdfcairo font "DejaVu Sans Mono,10"
set output 'dnsperf-dns_performance_qps.pdf'

# プロット要素
plot "dnsperf_result_simple.txt" using 1:2 with lines title "DNS QPS"

👉️plotで指定している「using 1:2」の具体的な意味は以下の通りです:

  • using 1:データファイルの1列目(Time)をx軸に使用
  • using 2:データファイルの2列目(qps)をy軸に使用

(2) dnsperf.sh

dnsperfコマンドを実行するShellスクリプトです。スクリプトdnsperf.shは、「chmod a+x dnsperf.sh」等を実行して、実行可能状態にしておいてください。

  • dnsperf_result.txt : dnsperfの計測結果と実行結果
  • dnsperf_result_simple.txt : gnuplotプロット用データ
dnsperf.sh
#!/bin/bash

# DNS Server
dns_server="192.168.10.1"

# 現在の年月日時刻を取得
timestamp=$(date +"%Y%m%d_%H%M%S")

# dnsperfコマンド実施
taskset -c 0-3 dnsperf -s "$dns_server" -d dns_queries.txt -q 1000 -Q 1000 -S 1 -l 60 > dnsperf_result.txt

# 生成データ整理
awk '/^[0-9]/ { if (base == 0) base = $1; print ($1 - base), $2 }' dnsperf_result.txt > dnsperf_result_simple.txt
cat dnsperf_result_simple.txt

# データ保存
cp dnsperf_result.txt "dnsperf_result_$timestamp.txt"
cp dnsperf_result_simple.txt "dnsperf_result_simple_$timestamp.txt"

# グラフ作成
gnuplot -p plot_dnsperf.gp

cp dnsperf-dns_performance_qps.pdf "dnsperf-dns_performance_qps_$timestamp.pdf"

※awkコマンドで、dnsperfが出力するデータ(dnsperf_result.txt)をgnuplotが解析できるようなシンプルなデータ(dnsperf_result_simple.txt)に変更しています。

(3) dnsperf の実行結果

dnsperf.shplot_dnsperf.gpの準備が揃ったら、dnsperf.shを実行してください。

Ubuntu
> ./dnsperf.sh

🍄実行結果はこちらです。

dnsperf_result_simple.txt (見やすく整形済み)
# time     responses_per_sec
0          402.001989
1.00417    493.940269
2.02658    496.863306
3.04882    474.452448
4.0711     518.447436
5.07484    503.118337
    ~ 省略 ~
53.5457    499.769187
54.5697    483.415905
55.5934    505.993780
56.6171    487.466542
57.641     504.926205
  • time : 実行開始からの秒数
  • responses_per_sec : 1秒あたりの応答数
dnsperf_result.txt (見やすく整形済み)
DNS Performance Testing Tool
Version 2.14.0

[Status] Command line: dnsperf -s 192.168.10.1 -d dns_queries.txt -q 1000 -S 1 -l 60
[Status] Sending queries (to 192.168.10.1:53)
[Status] Started at: Fri Oct 11 09:06:24 2024
[Status] Stopping after 60.000000 seconds
[Status] Testing complete (time limit)

Statistics:

  Queries sent:         44083
  Queries completed:    34190 (77.56%)
  Queries lost:         9893 (22.44%)

  Response codes:       NOERROR 23507 (68.75%), SERVFAIL 474 (1.39%), NXDOMAIN 10209 (29.86%)
  Average packet size:  request 38, response 94
  Run time (s):         64.764480
  Queries per second:   527.912831

  Average Latency (s):  0.312020 (min 0.000906, max 4.992433)
  Latency StdDev (s):   0.377774

< Response codesについて >

  • NOERROR : 名前解決が成功し、正常な応答が返された(IPがない場合でもエラーではない)
  • SERVFAIL : サーバー内部のエラーと応答(リソース不足、上位DNSへの問い合わせ失敗、構成エラーなど)
  • NXDOMAIN : 問い合わせたドメイン名が存在しないと応答

🦐 dnsperf の結果まとめ 🦐
テスト時間が「Run time(s):64.8」、正しくレスポンスが帰ってきたものが「Queries completed:34190」なので、DNS性能は「34190 queries / 64.8 second ≒ 528 qps」という結果が分かりました。

👉️DNSサーバ(ネットワークの環境や状況も含める)は、グラフやログ結果から分かる通り、約528qps出ているのが分かりました。

➐ resperf でグラフを作成

resperfでグラフを作成するため、resperfのコマンド用スクリプトと、gnuplotがグラフを作成するためのスクリプトを作成しておきましょう。

(1) 作図スクリプト1(QPS)の準備

gnuplotで作図するための設定(スクリプト)です。
こちらでは、主にクエリとレスポンスを確認します。

plot_resperf1.gp
# plot_resperf1.gp

set title "DNS Performance (resperf)"
set xlabel "Time (s)"
set ylabel "Queries per Second (qps)"
set xrange [0:60]       # x軸の範囲を 0 から 60 秒に設定
set yrange [0:*]        # y軸の範囲を 0 から 最大値までに設定
set xtics 5             # x軸の目盛りの間隔を10に設定
set ytics 100           # y軸の目盛りの間隔を50に設定
set grid
set format y "%4.0f"    # 整数を4桁で表示
set encoding utf8
set terminal pdfcairo font "DejaVu Sans Mono,10"
set output 'resperf-dns_performance_qps.pdf'

# プロット要素
# target_qps		:ツールが送信することを目指している目標のクエリ数やレスポンス数。
# actual_qps		:ツールが実際に送信したクエリの結果。
# responses_per_sec	:スループットを示す指標。処理できたリクエストの数です。
# failures_per_sec	:発生した失敗(エラー)の数。

plot "resperf_result.txt" using 1:2 with lines linecolor "red" title "Target QPS", \
     "resperf_result.txt" using 1:3 with lines linecolor "blue" title "Actual QPS", \
     "resperf_result.txt" using 1:4 with lines linecolor "purple" title "Responses per sec", \
     "resperf_result.txt" using 1:5 with lines linecolor "green" title "Failures per sec"

(2) 作図スクリプト2(Average Latency)の準備

gnuplotで作図するための設定(スクリプト)です。
こちらでは、主にクエリのレイテンシを確認します。

plot_resperf2.gp
# plot_resperf2.gp

set title "DNS Performance (resperf)"
set xlabel "Time (s)"
set ylabel "Average Latency (ms)"
set xrange [0:60]       # x軸の範囲を 0 から 60 秒に設定
set yrange [0:*]        # y軸の範囲を 0 から最大値まで設定
set xtics 5             # x軸の目盛りの間隔を5に設定
set ytics 0.1           # y軸の目盛りの間隔を0.1ミリ秒に設定
set grid
set format y " %1.1f"   # 4桁で表示
set encoding utf8
set terminal pdfcairo font "DejaVu Sans Mono,10"
set output 'resperf-dns_performance_AverageLatency.pdf'

# プロット要素
plot "resperf_result.txt" using 1:6 with lines linecolor "blue" title "Average Latency"

(3) resperf.sh

resperfコマンドを実行するShellスクリプトです。スクリプトresperf.shは、「chmod a+x resperf.sh」等を実行して、実行可能状態にしておいてください。

  • resperf_result.txt : gnuplotプロット用データ
  • resperf_result_dashbord.txt : resperf実行結果
resperf.sh
#!/bin/bash

# DNS Server
dns_server="192.168.10.1"

# 現在の年月日時刻を取得
timestamp=$(date +"%Y%m%d_%H%M%S")

# resperfコマンド実施
taskset -c 0-3 resperf -s "$dns_server" -d dns_queries.txt -r 60 -m 1500 -P resperf_result.txt > resperf_result_dashbord.txt

# 生成データ整理
cat resperf_result.txt

# データ保存
cp resperf_result.txt "resperf_result_$timestamp.txt"
cp resperf_result_dashbord.txt "resperf_result_dashbord_$timestamp.txt"

# グラフ作成
gnuplot -p plot_resperf1.gp
gnuplot -p plot_resperf2.gp

cp resperf-dns_performance_qps.pdf "resperf-dns_performance_qps_$timestamp.pdf"
cp resperf-dns_performance_AverageLatency.pdf "resperf-dns_performance_AverageLatency_$timestamp.pdf"

(4) resperf の実行結果

resperf.shplot_resperf1.gpplot_resperf2.gpの準備が揃ったら、resperf.shを実行してください。

Ubuntu
> ./resperf.sh

🍄実行結果はこちらです。

resperf_result.txt (見やすく整形済み)
# time   target_qps actual_qps responses_per_sec failures_per_sec avg_latency connections conn_avg_latency
  0.250     6.25       6.00      6.00             0.00            0.064832    0.00        0.000000
  0.750    18.75      18.00     18.00             4.00            0.219744    0.00        0.000000
  1.250    31.25      32.00     32.00             0.00            0.267448    0.00        0.000000
  1.750    43.75      42.00     42.00             0.00            0.112021    0.00        0.000000
  2.250    56.25      58.00     58.00             2.00            0.222725    0.00        0.000000
                                       ~ 省略 ~
 57.250  1431.25    1432.00    570.00             8.00            0.317608    0.00        0.000000
 57.750  1443.75    1442.00    572.00             8.00            0.323437    0.00        0.000000
 58.250  1456.25    1458.00    580.00             2.00            0.330593    0.00        0.000000
 58.750  1468.75    1468.00    602.00             4.00            0.310041    0.00        0.000000
 59.250  1481.25    1482.00    542.00            10.00            0.386928    0.00        0.000000
  • time : 実行開始からの秒数
  • target_qps : 1秒あたりのターゲットクエリ数
  • actual_qps : 1秒あたりの実際のクエリ数
  • responses_per_sec : 1秒あたりの応答数
  • failures_per_sec : 1秒あたりの失敗数(NOERROR または NXDOMAIN 以外の RCODE を持つ受信応答の数を、間隔の長さで割った値)
  • avg_latency : 平均レイテンシ(クエリの送信から応答の受信までの平均時間)
  • connections : この時間間隔中に行われた接続の数(再接続を含む)。TCP や DoT などの接続指向プロトコルにのみ関連。
  • conn_avg_latency : 平均接続遅延。接続を開始してからクエリの送信準備が整うまでの平均時間。TCP や DoT などの接続指向プロトコルにのみ関連。
resperf_result_dashbord.txt
DNS Resolution Performance Testing Tool
Version 2.14.0

[Status] Command line: resperf -s 192.168.10.1 -d dns_queries.txt -r 60 -m 1500 -P resperf_result.txt
[Status] Sending
[Status] Waiting for more responses
[Status] Testing complete

Statistics:

  Queries sent:         45000
  Queries completed:    28885
  Queries lost:         16115
  Response codes:       NOERROR 19975 (69.15%), SERVFAIL 466 (1.61%), NXDOMAIN 8444 (29.23%)

  Run time (s):         100.000000
  Maximum throughput:   742.000000 qps
  Lost at that point:   40.26%

  Connection attempts:  0 (0 successful, 0.00%)

< Response codesについて >

  • NOERROR : 名前解決が成功し、正常な応答が返された(IPが取得できない場合でもNOERROR)
  • SERVFAIL : サーバー内部のエラーと応答(リソース不足、上位DNSへの問い合わせ失敗、構成エラーなど)
  • NXDOMAIN : 問い合わせたドメイン名が存在しないと応答

🦑 resperf の結果まとめ 🦑
60秒かけてDNSクエリを1,500qpsまで上げてみました。25秒過ぎあたりからレスポンスの一部が返却されなくなってきています。返却されないクエリは、負荷のためDNSサーバで破棄されていると推測されます。DNSサーバ(ネットワークの環境や状況も含める)は、グラフやログ結果から分かる通り、スループットは最高で742qps出ているのが分かりました。

👉️DNSの性能としては(正しくDNSレスポンスまで処理できているのは)、グラフから500~600qps前後と分かるので、dnsperfの結果と大体一致しているのが分かりますね。

➑ ツール一式

今回のファイルは以下にまとめておきます。
良かったらダウンロードして、遊んでみてください。

➒ さいごに🔔

dnsperfresperfは、アプローチの違いはあれ、ほぼ同じ結果を示しました。今回は逆の手順となりましたが、最初にresperfでおおよその限界値を調べておき、その後、dnsperfで正確なDNS性能(qps)を調査するのが良かったのかもしれません…

いずれにせよ、DNS性能のみならず、ネットワークの構成や状態、ツールのオプション、ツールを実行するPCのスペックや台数等も、負荷試験に関係してきますので、ある程度正しく計測できるまで、各々を微調整しながら負荷試験をエンジョイしてみてください😉

それでは、今年も1年お疲れさまでした😊    :lgtm:👈️ポチっ

🎄 Advent Calendar アーカイブ 🎄

🥷2024 サクラエディタをオレオレ仕様に!カスタマイズ術
🥷2024 DNSのスループット、ボクが測ってみた!
🐾2023 【初学者必見】C言語 ジャンプテーブルを使って自動販売機をプログラミングしよう
🐾2022 【おとなの社会学】ポイント経済の仕組み
🐾2021 【webアプリ】画像の背景透過処理を行うwebサービスを作ってみた
🐾2020 【簡単】TeachableMachineを利用して「ゴクリAI認識」webアプリを作ろう

0
0
0

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?