2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ISUCONで学ぶGo private-isu環境構築編 alp,pprof,pt-query-digestの導入方法

Last updated at Posted at 2024-10-12

IsuconでGoの勉強をしてみる

今回初めてisuconに出ることになり、色々調べてみるとほとんどのチームがGoを使うことがわかった。初心者としては情報が多い方が良さそうなので使ったことはないがGoで挑戦することを決意。
どうやってGoを学ぼうか迷っていたが、Goの書き方やら環境構築やらを行うのがめんどうなので、いっそのことisuconの過去問を眺めながらGoについて学ぶことにした。

筆者のスペック

  • 大学生
  • バックエンドを中心に一年位インターン
  • Go未経験
  • Isucon未経験

環境構築

今回導入するツールは

  • alp(nginxログ監視ツール)
  • pt-query-digest
  • pprof

まずは環境構築や、問題を解くためのツールの導入などをおこなう。
以下の記事を参考にしてmultipassで環境構築を行なった。
今回解くのはisuconの練習問題であるprivate-isu

今回はgoで練習したいのでマニュアルを参考にして以下のコマンドを実行

$ sudo systemctl stop isu-ruby
$ sudo systemctl disable isu-ruby
$ sudo systemctl start isu-go
$ sudo systemctl enable isu-go

multipassでIPアドレスを調べて、https://{IPアドレス}にアクセスし、以下のようなサイトが表示されれば成功

image.png

ベンチマークを回してみる。

{"pass":true,"score":4055,"success":3914,"fail":0,"messages":[]}

問題なく実行できた

各種ツールの導入

まず初めにvscodeからアクセスできるようにsshキー登録する。
まずローカル側で鍵の作成。

cd ~/.ssh
ssh-keygen -t rsa -f id_rsa_isu

公開鍵をコピー

cat id_rsa_isu.pub

multipassインスタンスに~/.ssh/authorized_keysを作成し、先ほどのコピーを追加

cd ~/.ssh
touch authorized_keys
chmod 600 authorized_keys
vi authorized_keys

ローカルから接続できることを確認

ssh isucon@***.***.***.*** -i ~/.ssh/id_rsa_isu

あとはvscodeからリモート接続できれば完了

alp

alpが一番有名そうなので今回はこちらを使用してみる。
以下のコマンドでダウンロード

wget https://github.com/tkuchiki/alp/releases/download/v1.0.9/alp_linux_arm64.tar.gz
tar -zxvf alp_linux_arm64.tar.gz
sudo install alp /usr/local/bin/alp

その後、以下を実行して動作確認

alp --version

次にnginxでログを出力するように設定

sudo vi /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;

pt-query-digest

次はsqlのログを取得するためのツールを導入
/etc/mysql/conf.d/my.cnfでmysqlの設定が行えるらしいがなぜかそのファイル自体がなかったので以下のコマンドで探してみる

isucon@private-isu:~$ sudo find / -name my.cnf
find: ‘/proc/89099’: No such file or directory
find: ‘/proc/89100’: No such file or directory
find: ‘/proc/89101’: No such file or directory
/tmp/private-isu/ansible_old/roles/portal/files/mysql/my.cnf
/var/lib/dpkg/alternatives/my.cnf
/etc/alternatives/my.cnf
/etc/mysql/my.cnf
/home/isucon/private_isu.git/ansible_old/roles/portal/files/mysql/my.cnf

/etc/mysql/my.cnfにあるらしいので開いてみる

sudo vi /etc/mysql/my.cnf
#
# The MySQL database server configuration file.
#
# You can copy this to one of:
# - "/etc/mysql/my.cnf" to set global options,
# - "~/.my.cnf" to set user-specific options.
# 
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html

#
# * IMPORTANT: Additional settings that can override those from this file!
#   The files must end with '.cnf', otherwise they'll be ignored.
#

!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/

この内容をみるとMySQLの設定は/etc/mysql/conf.d/や/etc/mysql/mysql.conf.d/ディレクトリ内の.cnfファイルによって追加または上書きできるようになっている。
よって、以下のように新しくファイルを作成して設定を書き込む。

sudo vi /etc/mysql/conf.d/custom-my.cnf
[mysqld]
character-set-server=utf8mb4
slow_query_log=ON
long_query_time=0.001
slow_query_log_file=/var/log/mysql/my-slow.log

[mysql]
default-character-set=utf8mb4

[client]
default-character-set=utf8mb4

ログを出力するファイルに書き込み権限を与える

sudo mkdir -p /var/log/mysql
sudo chown mysql:mysql /var/log/mysql

再起動

sudo systemctl restart mysql

その後percona-toolkitをインストール(この中にpt-query-digestが含まれる)

sudo apt install -y percona-toolkit

その後にbenchを回した後に以下のコマンドを実行

sudo pt-query-digest /var/log/mysql/my-slow.log > ~/pt-query-digest.txt

以下のようなファイルが作成されれば成功

# 1.8s user time, 390ms system time, 40.54M rss, 47.60M vsz
# Current date: Sat Oct 12 00:48:34 2024
# Hostname: private-isu
# Files: /var/log/mysql/my-slow.log
# Overall: 25.73k total, 27 unique, 0.55 QPS, 0.04x concurrency __________
# Time range: 2024-10-11T02:32:18 to 2024-10-11T15:36:18
# Attribute          total     min     max     avg     95%  stddev  median
# ============     ======= ======= ======= ======= ======= ======= =======
# Exec time          1886s     1ms      1s    73ms   155ms    51ms    56ms
# Lock time           82ms       0    13ms     3us     1us   129us       0
# Rows sent          3.96M       0   9.77k  161.26    6.98   1.17k    0.99
# Rows examine       2.07G       0  97.68k  84.50k  97.04k  32.68k  97.04k
# Query size        14.46M      10   1.17M  589.02   80.10  21.26k   65.89

# Profile
# Rank Query ID                      Response time   Calls R/Call V/M   It
# ==== ============================= =============== ===== ====== ===== ==
#    1 0x624863D30DAC59FA16849282... 1192.1396 63.2% 10026 0.1189  0.01 SELECT comments
#    2 0x422390B42D4DD86C7539A5F4...  516.1626 27.4% 10960 0.0471  0.01 SELECT comments
#    3 0x100EC8B5C400F34381F9D7F7...  116.6155  6.2%   934 0.1249  0.01 SELECT comments
# MISC 0xMISC                          61.2725  3.2%  3815 0.0161   0.0 <24 ITEMS>

# Query 1: 0.21 QPS, 0.03x concurrency, ID 0x624863D30DAC59FA16849282195BE09F at byte 4566541
# This item is included in the report because it matches --limit.
...

pprofの導入

手順概要

  1. Goアプリケーションにpprofを組み込む
  2. pprofサーバーを有効にする
  3. プロファイルデータを取得
  4. ローカルでプロファイルデータを分析
  5. グラフ化して視覚的に分析

1. Goアプリケーションにpprofを組み込む

Goアプリケーションでpprofを利用するには、net/http/pprofパッケージをインポートして、プロファイリング用のエンドポイントを有効にする必要があります。main.goやアプリケーションのエントリーポイントで以下のようにコードを追加します。

例: pprofのインポートと設定

import (
    _ "net/http/pprof"
    "log"
    "net/http"
)

func main() {
    // pprof用のHTTPサーバーを起動 (ポート6060)
    go func() {
        log.Println(http.ListenAndServe("localhost:6060", nil))
    }()

    // アプリケーションの他のコード
}
  • この設定により、http://localhost:6060/debug/pprof/にアクセスすることで、pprofのプロファイリング機能が利用可能になります。
  • go func()内で別ゴルーチンを使ってpprofサーバーをバックグラウンドで起動しています。
  • Go初心者ならではかもしれないが、goはコンパイル言語なので、以下のコマンドでbuildしないと変更が反映されないことに注意(アプリの再起動も)
go build -o app
sudo systemctl stop isu-go
sudo systemctl restart isu-go

2. pprofサーバーを有効にする

pprofが正しく起動しているか確認します。アプリケーションが実行中のサーバーにアクセスし、pprofのエンドポイントが利用可能かどうかを確認します。

curl http://localhost:6060/debug/pprof/
  • 正常に動作している場合、pprofのエンドポイントの一覧が表示される。

3. プロファイルデータを取得

pprofのエンドポイントからプロファイルデータを収集します。たとえば、CPUプロファイルを60秒間収集する場合、次のコマンドを実行。

CPUプロファイルの取得例

go tool pprof http://localhost:6060/debug/pprof/profile?seconds=60

このコマンドを実行すると、60秒間のプロファイルデータが収集され、pprofのインタラクティブな解析環境が起動します。

4. ローカルでプロファイルデータを分析

取得したプロファイルデータをローカルでさらに分析することも可能です。プロファイルデータをファイルとして保存し、後から解析できるらしい。

プロファイルデータの保存と解析

# プロファイルデータを保存
curl -o profile.pb.gz http://localhost:6060/debug/pprof/profile?seconds=60

# 保存したプロファイルデータを解析
go tool pprof profile.pb.gz

これにより、pprofの解析インターフェースが起動し、データを対話的に分析できる。
ただ、このprofile.pb.gzがあれば解析はできるので、以下ではこのファイルをローカルに落としてweb上で解析してみる

5. グラフ化して視覚的に分析

pprofの解析インターフェースでGraphvizを利用して、プロファイルデータを視覚的にグラフ化できる。まず、Graphvizをインストール。

Graphvizのインストール(macOSの場合)

brew install graphviz

グラフの表示

pprofのインターフェース内で以下のコマンドを実行して、グラフをWebブラウザで表示。

go tool pprof profile.pb.gz
(pprof) web

これにより、ブラウザでグラフ化されたプロファイルデータを見ることができる。また、SVGやPNG形式でグラフを生成することも可能

成功すると以下の様なサイトが開く
image.png

まとめ

次回はこの環境を用いてGoの勉強をしながらパフォーマンス改善を行う

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?