<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>saity dev</title>
    <link>https://www.saity.dev/</link>
    <description>Recent content on saity dev</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>ja</language>
    <lastBuildDate>Sat, 01 Nov 2025 10:59:32 +0900</lastBuildDate><atom:link href="https://www.saity.dev/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Linux環境でのDockerマウント時のパーミッション問題について調査してみた</title>
      <link>https://www.saity.dev/posts/docker-mount-permission/</link>
      <pubDate>Sat, 01 Nov 2025 10:59:32 +0900</pubDate>
      
      <guid>https://www.saity.dev/posts/docker-mount-permission/</guid>
      
      <description>はじめに Dockerコンテナでホストのディレクトリをマウントする際、パーミッションの問題に直面することがあります。具体的にはコンテナ側でマウントしたデータが読み込めなかったり、コンテナで作成したものをホスト側で編集できなかったりなどのケースがあります。UbuntuDesktop環境で実際にいろいろ試してみて、そのよう問題について調査したのでそれを共有します。
確認したいこと ホスト側とコンテナ側でのパーミッションの違いがあるかどうか ホスト側（またはコンテナ側）で権限を変更した場合、どちらにも反映されるか ホスト側(またはコンテナ側)でファイルやディレクトリを作成したとき、もう片方では読み込めるか コンテナを２つ立てて同じように起動すれば、相互でファイルやディレクトリを読み込むことができるか 1. ホスト側とコンテナ側のパーミッションの違い shareディレクトリをホスト側で作成し、コンテナ側にマウントする。
secはホスト側のユーザー名です。
ホスト:
&amp;gt;ls -al drwxrwx--- 2 sec sec 4096 11月 1 16:22 share コンテナ:
&amp;gt;ls-al drwxrwx--- 2 1000 1000 4096 Nov 1 07:22 share secユーザーのidを確認する。
sec@sec-System-Product-Name:~/test/docker_bind_mound$ id uid=1000(sec) gid=1000(sec) groups=1000(sec),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),114(lpadmin),984(docker) user_id,group_id,permissionも一致している ホストのuser_id,group_id,パーミッションがそのままコンテナのディレクトリに反映されることがわかる。
2. ホスト側（またはコンテナ側）で権限を変更した場合、どちらにも反映されるか まずコンテナ側でpermissionを770=&amp;gt;700に変更してみる
その操作の後、ホスト側でパーミッションを確認する
&amp;gt;ls -al drwx------ 2 sec sec 4096 11月 1 16:22 share 変更されている。 user_id,group_idが同じだからできるっぽい。
今度はホスト側でpermissionを700=&amp;gt;770に戻してみる。 その操作の後、コンテナ側でパーミッションを確認した。
=&amp;gt;ちゃんと770に戻っている。
3. ホスト側(またはコンテナ側)でファイルやディレクトリを作成したとき、もう片方では読み込めるか コンテナ側でファイルを作成してみる。
root@08e5c8531d86:/app/share# touch test.txt root@08e5c8531d86:/app/share# ls -al -rw-r--r-- 1 root root 0 Nov 1 07:38 test.</description>
      
    </item>
    
    <item>
      <title>IPフラグメンテーションが起こる様子をWiresharkで確認する</title>
      <link>https://www.saity.dev/posts/check_ip_fragmentation/</link>
      <pubDate>Fri, 06 Jun 2025 20:01:49 +0900</pubDate>
      
      <guid>https://www.saity.dev/posts/check_ip_fragmentation/</guid>
      
      <description>はじめに 大きいデータを送信すると、経路上でデータが複数に分割されることがある(IPフラグメンテーション)。これをWiresharkで実際に確かめたい。
手順 Wiresharkを起動して、パケットをキャプチャする。フィルタリングは以下のようにすればいい。 ip.addr==&amp;lt;任意のIPアドレス&amp;gt; 以下のPythonコードを実行して、UDPパケットを送信する。 import socket # 送信先のIPアドレスとポート番号 UDP_IP = &amp;#34;任意のIPアドレス&amp;#34; # ※ループバックアドレスは使わないこと UDP_PORT = 5005 # 65,000バイトのデータを作成 MESSAGE = b&amp;#34;ABCDEFGHIJKLMNOPQRSTUVWXYZ&amp;#34; * 1000 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto(MESSAGE, (UDP_IP, UDP_PORT)) print(f&amp;#34;Sent {len(MESSAGE)} bytes to {UDP_IP}:{UDP_PORT}&amp;#34;) ※注意点 udp.port==5005とフィルタリングするとうまくいかない
今回見たいのは、送信するUDPデータグラムとそれらが分割されてできた複数のIPパケットである。そのため、UDPポートでフィルタリングしてしまうと、portフィールドがあるUDPデータグラムしか表示されない。IPパケットはUDPのヘッダがないので、フィルタリングで弾かれてしまう。
ループバックアドレスだとうまくいかない
最初はsenderとreceiverを用意してデータグラムを送受信させるプログラムを書いたが、この場合だとうまくいかなかった。ループバックアドレスはルーターを経由しないため、そもそもIPパケットが分割されないという可能性がある。
結果 以下のようにいくつかのIPパケットとそれらが構成されてできたUDPデータグラムが表示される。 今回は送信側のキャプチャ結果を示しているので、IPパケットの順序は基本的にオフセットの小さい順になっている。ちなみにオフセットの間隔は1480バイトとなっているが、これは一度に送れるIPパケットの最大サイズ(MTU)が1500バイトで、そこからIPヘッダのサイズを引いた値である。
まとめ 本当は受信側でやりたかったが、ループバックアドレスを使うとIPフラグメンテーションが起きないため、ひとまず送信側でやった。 受信側でやるとIPパケットの到着順序がばらばらになったり、そこから送信時の順序通りに正しく再構築されることを確認できるので面白いと思う。気が向いたらやってみたい。
参考 Wireshark Fragmented Packet Capturing
https://youtu.be/1gX_-DqGNxA?si=cG_gh3P9YuzK1k5L</description>
      
    </item>
    
    <item>
      <title>同一ネットワーク上にあるUbuntuサーバーからWSLへHTTPリクエストを送る</title>
      <link>https://www.saity.dev/posts/local_network_device_to_wsl/</link>
      <pubDate>Sun, 18 May 2025 16:14:51 +0900</pubDate>
      
      <guid>https://www.saity.dev/posts/local_network_device_to_wsl/</guid>
      
      <description>はじめに 同一ネットワーク上にあるUbuntuサーバーからWSLで起動したAPIサーバーにHTTPリクエストを送ろうとしたらうまくできなかった。すぐ終わりそうだと思ったら意外とハマったのでメモしとく。
概要 簡単に書くと上図のような構成になっている。今回うまくいかなかった、またはよく分からなかったのは以下の部分。
リクエスト先として指定するIPアドレス どこでリクエストがブロックされているのか(Windowsマシンに届く前か、WSLに届く前か) 解決法 まず大前提として、リクエスト先のIPアドレスはWSLのIPアドレスではなく、WindowsのIPアドレスを指定する。これはipconfigコマンドで知ることができる。となると、Windowsマシンでポートを一時的に開ける必要があることもわかる。今回はひとまず、TCPの18080を開放した。次はWindowsでのIPアドレスとポートをWSLのIPアドレスとポートにマッピングするような設定を行う必要がある。これはnetshコマンドを使って以下のように設定できる。
# 192.168.1.yyy:18080 =&amp;gt; 192.168.zzz.zzz:8080 netsh interface portproxy add v4tov4 listenport=18080 listenaddr=192.168.1.yyy connectport=8080 connectaddress=192.168.zzz.zzz # 設定できているか確認 netsh interface portproxy show all これでUbuntuサーバーからWindowsマシンのIPアドレスとポートを指定してリクエストを送ると、WSLで起動したAPIサーバーにリクエストが届くようになる。
感想 WSLのネットワーク事情だったりIP層の基礎的なところがよくわかってなかったのでかなり手こずってしまった。次回はもう少しいい感じに問題解決できるようにしたい。
参考 wsl2 で立てたサーバーにローカルネットワーク内の他の端末からアクセスする Windows内のネットワークを整理：②WSL2編 Windows/Linuxでポートフォワーディングする方法 </description>
      
    </item>
    
    <item>
      <title>競プロ典型90問☆４ざっくりメモ</title>
      <link>https://www.saity.dev/posts/typical90-star4/</link>
      <pubDate>Tue, 25 Mar 2025 18:12:08 +0900</pubDate>
      
      <guid>https://www.saity.dev/posts/typical90-star4/</guid>
      
      <description>競プロ典型90問 https://atcoder.jp/contests/typical90
☆４はatcoder problems Difficultyが800 ～ 1199、ABC換算だと400点問題(D問題)レベルらしい。 とりあえず全部やったので雑にメモ+振り返り
https://atcoder.jp/contests/typical90/tasks/typical90_a 答え 最大の長さを求める問題から長さXを作れるかという判定問題に 二分探索
欲しい値の取りうる範囲が大きい場合、それをlog(n)で出せる方法。
欲しい値がちょうど条件の境界線にある場合に有効。
ex.最大の中の最小値,条件を満たす中での最大値
そのようなケースは数列の単調増加(減少)がある場合に見られる。数列ではなく、実数上でも有効
https://atcoder.jp/contests/typical90/tasks/typical90_c 答え 木
木の直径を求め、そこから最大の閉路を求める。
木の直径は以下の手順で求める。
1.任意の頂点から一番深い頂点をdfsで求める。それをuとする。
2.uからもう一度dfsし、uから一番深い頂点をvとする。
3.uからvまでのパスが木の直径
https://atcoder.jp/contests/typical90/tasks/typical90_h 答え ナップサック問題
各状態の個数を持っておきDP
この場合は{&amp;ldquo;a&amp;rdquo;,&amp;ldquo;at&amp;rdquo;,&amp;ldquo;atc&amp;rdquo;,&amp;hellip;}のように文字をpushした時点での状態（個数）を保持
https://atcoder.jp/contests/typical90/tasks/typical90_l 答え UnionFind
赤マスの連結状態をチェック
グリッド上での操作をグラフとしてみる。
たどり着ける＝＞２端点は同じ連結成分
https://atcoder.jp/contests/typical90/tasks/typical90_z 答え 木
どの頂点も隣り合わない＝＞二部グラフ
二部グラフを生成し、N/2より多いグループの頂点をN/2個出力
二部グラフの特徴は奇数閉路を持たないこと。
木は二部グラフ
https://atcoder.jp/contests/typical90/tasks/typical90_ab 答え imos法
+&amp;hellip;.-..
&amp;hellip;&amp;hellip;..
&amp;hellip;&amp;hellip;..
-&amp;hellip;.+..
左から右への累積のあと、上から下への累積
https://atcoder.jp/contests/typical90/tasks/typical90_ah 答え 尺取法
実装詰まりがち
とりあえず、半開区間を[l,r)として定義し、lをfor文で回しながらrをできるだけ右に持っていくような実装にする。
https://atcoder.jp/contests/typical90/tasks/typical90_ap 答え メモ化再帰orDP
DPだとO(k^2)になると勘違いしてた。
https://atcoder.jp/contests/typical90/tasks/typical90_aq 答え 単純にBFSでやるとまずい
例えば、vからuへの経路でくねくねしてる短い道と真っ直ぐの多い遠回りな道の２つがあるとする。
頂点を一度しか調べない単純なbfsをした場合、uに先にたどり着くのは前者の経路であるが、実際は後者が最適経路。
ダイクストラ法を用いる。
priority_queueで方向転換回数が少ないものを優先的に取り出す。
前述の例だと遠回りでも後者が先にuにたどり着いて最小コストを記録できる。
この場合、各頂点にどちらの方向を向いてるかの状態を保持させるといい。
グリッド上での探索問題は様々なケースを考慮した上で最適なアルゴリズムやデータの持ち方を選択することが重要
https://atcoder.jp/contests/typical90/tasks/typical90_bf 答え ボタンを2^x回押した時の今表示されている数字の遷移先を考える。2^x回の遷移先は2^(x-1)の遷移を２回行ったものであることがポイント。</description>
      
    </item>
    
    <item>
      <title>ABC221 C問題 別解</title>
      <link>https://www.saity.dev/posts/abc221c_other_solution/</link>
      <pubDate>Sun, 16 Mar 2025 19:34:55 +0900</pubDate>
      
      <guid>https://www.saity.dev/posts/abc221c_other_solution/</guid>
      
      <description>ABC221 C問題　Select Mul https://atcoder.jp/contests/abc221/tasks/abc221_c 答え↓ 想定解法 各桁を並び替えて、その並び替えた数列のどこかに１つ区切りを挿入することを考える。各桁の並び替えの全探索と区切りの入れ方から計算量はO((L-1)L!)。(Lは桁数)
別解 空の文字列A,Bに各桁の数字をどちらに、どのような順番で入れれば、A*Bが最大になるかを考える。まず、A,Bどちらかに数字を入れるときは数字のでかいものから入れるほうが良いということがわかる。そのため、各桁での数字を降順でソートしておく。次に各イテレーションでA,Bどちらにpushするのが最適かを考える必要があるが、結論から言うとこれは現時点でのA,Bを比較したときに値が小さい方にpushする方が良い。下の例のように処理を行う。赤下線がpushした数字で直前のA,B間の大小関係でどちらにpushするかを決めている。 &amp;lt;証明&amp;gt;
A,B($A \geqq B$)とpushする数字Xがある。
Aにpushした場合: $$ (10A + X)\times B=10AB+BX $$ Bにpushした場合: $$ (10B+X)\times A=10AB+AX $$
$A \geqq B$より、Bにpushした方が次の$A\times B$の値が大きくなる。終
また、Nに0が含まれている場合は、その0を取り除いておき、後でpow(10,zero_count)を掛けてやれば良い。この方法における計算量は、ソートがボトルネックとなっているため、O(L*log(L))
提出：
https://atcoder.jp/contests/abc221/submissions/63879675 考えたこと 0があることに関しては、0である桁数さえ持っていれば取り除いてしまって良い。（一番末尾に0が来たほうが最適であることと、出力するものが掛け算であるために、A,Bどちらへの挿入でも結果は変わらないことから） 各桁を降順ソートすること。(大きい数字をa,bの大きい位に入れていくため) 「A,Bに大きい順で数字を交互に入れていけばいい？」と雑に考えたが、WA。反例は98321。9をA,8をBに入れた後、もう一度Bに8を入れる必要がある。 </description>
      
    </item>
    
    <item>
      <title>ネスペ合格したので何やったかを簡単に書く</title>
      <link>https://www.saity.dev/posts/network_specialist/</link>
      <pubDate>Sat, 06 Jul 2024 18:19:18 +0900</pubDate>
      
      <guid>https://www.saity.dev/posts/network_specialist/</guid>
      
      <description>書籍 マスタリングTCP/IP(https://amzn.asia/d/05kUpRdT) とりあえずひたすら読んだほうがいいやつ。これを読んでネットワーク技術関連の体系的な知識や考え方みたいなものが身についたのかなと思います。圧倒的おすすめ
ネットワークはなぜつながるのか(https://amzn.asia/d/09RvkCty) 難易度はそこまで高くないですが、マスタリングと比べて少し細かい話が多いイメージ。身の回りのネットワーク知識（FTTHやADSLなどの回線に関する話）についての解説が多いので読んでいて面白かったです。
ネットワーク技術＆設計入門(https://amzn.asia/d/0dXPv44s) ネットワーク技術だけでなく、設計にも焦点を置いた本で少し難しかったです（特に後半）。部分的に重要なところをピックアップして読んでいたという形です。
メール技術の教科書(https://amzn.asia/d/0hthXWDm) メールサーバーの仕組みとgmailのガイドライン改定に関心があったので、買って読みました。メール技術に関する知識に絞ってあるので、他の書籍では書いてないようなことが知れて面白かったです。ちょうど自分が受けた試験の午後２がたまたまメールサーバーの話だったのでラッキーでした。
ネットワークスペシャリスト合格教本(https://amzn.asia/d/0hXxDln4) ネスペ対策本として選んだ一冊目の書籍。
ALL IN ONE ネットワークスペシャリスト(https://amzn.asia/d/07hJ3S0f) ネスペ対策本２冊目。一冊目をほぼ読み終えてしまってモチベーションが低下していたので買いました。
Webサイト 過去問道場(https://www.nw-siken.com/nwkakomon.php) 午前２はとりあえずこれをやりました。
IPAが公開している過去問(https://www.ipa.go.jp/shiken/mondai-kaiotu/index.html) 午後１、２はこれでやりました。
ネットワークエンジニアとして(https://www.infraexpert.com/) わからないことを調べると大体上の方に出てくるのでブックマークしていました。適当に興味あるものを見ているだけでも面白いです。
cloudflare ラーニングセンター(https://www.cloudflare.com/ja-jp/learning/) DDoS,CDN,DNSなど、アプリケーション層の話が多めです。こちらも適当に興味あるものを見て知識を深めるという感じでやってました。
その他やったこと webアプリケーション作成 isuconとかポートフォリオ作成とかでwebアプリケーションを実装することによってアプリケーション層の知識が深められました。
socketライブラリを用いた簡易的な通信アプリケーションをpythonで実装 TCPやUDPの挙動の理解を深めるために役立ったと思います。
wiresharkで遊ぶ パケットを監視して、低層(2,3,4層)でどのような処理を行っているかの理解を深めました。特にヘッダーのパラメータを見てみて、理論上学んできたことが実際に使われていることを確認するのはためになると思います。
今後の課題 もう少し専門的な知識を身につけるようにする。(いろんな書籍や記事を読む。面白いと思った技術はとことん調べる) webアプリを作ったりプログラミングを学ぶ過程でネットワークに関する問題がちらつけばできるだけ深掘りするようにする。 </description>
      
    </item>
    
    <item>
      <title>線形代数の学び直し[線形代数のエッセンス]</title>
      <link>https://www.saity.dev/posts/vector_study/</link>
      <pubDate>Tue, 05 Mar 2024 14:09:26 +0900</pubDate>
      
      <guid>https://www.saity.dev/posts/vector_study/</guid>
      
      <description>3Blue1Brownが出している線形代数のエッセンス(https://youtube.com/playlist?list=PL5WufEA7WHQGX7Su06JzbPDXUQGOd0wlq&amp;amp;si=x98fuVYKHjpSN0PE)が見ていて学び直しにとても役に立ったと感じました。学び直しだけでなく、これから線形代数を学ぶという方にもおすすめできる内容だと思いました。自分はこれを見て、今まで適当に線形代数をやっていたんだと思い知らされました。 具体的には&amp;hellip;
Spanや基底ベクトルについての理解。特にspanが何を表しているのかをしっかり理解できました。 正方行列、非正方行列の意味やそれによる変換がやっていることについて。平面上にある格子線が変形されていくアニメーションがとてもわかりやすい。 行列式がなにを表しているか。 内積や外積の意味について。特に内積がなぜ各要素の積の総和を取るのかがよくわかりました。 クラメルの公式の導出をちゃんと理解できました。今まで丸暗記していました。。 固有値や固有ベクトルが何を表しているかについて。定義からみてもなんとなくわかりますが、アニメーションによる説明で理解が深まりました。 今まで適当にながしていた用語や数式の意味をある程度知ることが出来ました。(span,行列式,rank,trace,kernelなど) これ以外にも、重要な知識や考え方が説明されていたので、定期的に復習し直すのが良いと思いました。</description>
      
    </item>
    
    <item>
      <title>Windows11の再インストール手順をマニュアル化</title>
      <link>https://www.saity.dev/posts/windows_init/</link>
      <pubDate>Wed, 27 Dec 2023 08:55:11 +0900</pubDate>
      
      <guid>https://www.saity.dev/posts/windows_init/</guid>
      
      <description>はじめに これまでWindowsの再インストールは何度かやってきましたが、バックアップの確認、再インストール手順の確認、インストールされていたソフトや設定ファイルの内容を思い出すなど、やることが多くて毎回苦労していました。
そこで、今回はWindowsの再インストールの手順や注意事項、インストール自動化（完全に自動ではない）スクリプトをまとめたリポジトリを作成して、Windows再インストール手順のマニュアルを作成しました。Windowsの再インストールが面倒くさいと感じている方や、Windowsをこれから使うというような方に、なにか役立つ情報を共有できればいいなと思っています。
(注意: Windowsのインストール完了までの詳しい手順はここではあまり詳しくは書かないので、公式のドキュメントや別のサイトを参考にするようにしてください。)
バックアップをとっておく 必要なものをバックアップとして別のドライブ、またはUSBメモリにコピーしておきましょう。ちなみに自分は必要なデータはほぼOneDriveや別ドライブに保存しているため、バックアップはsshの秘密鍵が格納されている.sshフォルダのみで十分でした。あとvscodeの設定ファイルとかもありますね。面倒であれば、Usersフォルダごとバックアップを取るでもいいかもしれないです。
インストールメディアを作成する 16Gb以上のUSBを使ってWindowsのインストールメディアを作成します。
下記リンクにある上から３つ目の項目からISOファイルをダウンロードします。
https://www.microsoft.com/en-us/software-download/Windows11
続いて、rufusと呼ばれるisoファイルからインストールメディアを作成するツールをダウンロードします。
https://forest.watch.impress.co.jp/library/software/rufus/
このrufusを起動して、先程ダウンロードしたisoファイルと使うUSBメモリを指定してインストールメディアを作成します。
Windowsをインストールする Bios画面を開き、指定のUSBが起動するように設定します。もう一度再起動すると、Windowsのインストール画面が表示されるので、決まった手順でインストールまで進めます。
wingetでgitをインストール シェルスクリプトでwingetを回したいので、git bashをとりあえず手動でインストールします。
winget install -e -i Git.Git (注意：wingetでこのコマンドを実行しても反応がなくて、うまくいかないことがありました。自分はwingetのバージョンを最新のものにすることで解消できました。
実際の手順は以下のブログが参考になるかもしれないです。
https://zenn.dev/kawamasato/articles/11c4477e101374)
セットアップ用のシェルスクリプトファイルを実行する。 インストールしたいツールやアプリのインストーラーを順番に実行していきます。 git bashを開き、以下のコマンドを実行します。
bash setup.sh 自分が使ったファイルの中身は以下のようになっています。
#Install Software #Tool winget install -e -i 7zip.7zip # 解凍,圧縮ソフト winget install -e -i CPUID.HWMonitor # CPU,GPUなどの状態監視ツール winget install -e -i Maxon.CinebenchR23 # CPU ベンチマーク計測ソフト winget install -e -i CrystalDewWorld.CrystalDiskInfo # SSD 状態管理 winget install -e -i CrystalDewWorld.</description>
      
    </item>
    
    <item>
      <title>isucon13に参加しました</title>
      <link>https://www.saity.dev/posts/isucon13_result/</link>
      <pubDate>Mon, 27 Nov 2023 16:31:21 +0900</pubDate>
      
      <guid>https://www.saity.dev/posts/isucon13_result/</guid>
      
      <description>はじめに isucon13に参加してきました。
チームは同い年(修士1年)の３人チームで、全員isucon参加は初でした。
結果としてスコアは22284点で108位という結果でしたが、訳あって再起動試験（追試）でエラーを吐いて失格となってしまいました。(このあたりは後ほど説明します)
チーム構成と役割 全員同い年で学生チームとして参加しました。 各メンバーとそれぞれの役割は以下のとおりです。
saity : 私。インフラ担当, 手が空いてる時はGoの実装をする。 auaua : App,DB担当(主にDB) kentakunkentakun : App,DB担当(主にGoの実装) 最初のセットアップ(ssh接続やMakefileの編集など)は自分がやり、他メンバー２人はDBのインデックスを貼ることやGoの実装などをメインでやってくれました。とはいっても、最初のセットアップが終われば自分も２人と一緒にチューニング作業をしました。
予行練習 予行練習として、私達は週一で４,５回ほどオフラインで集まって過去問を解くということをしました。本番も同じように現地で集まって行いました。オフラインにしたのはコミュニケーションが取りやすく、情報共有が容易であるという理由からです。この予行練習ではチューニングに必要な環境構築や具体的にどのようなチューニングをするべきかの目処を立てるというのが主な目的でした。前者は主に以下の内容を指しており、ここを詰まらせないようにするかが最初のポイントでした。
ssh接続 Makefileの編集 ベンチを回す。 alpやslow-queryを見る マニュアルを読む git運用方針 3回目ほどで環境構築は慣れてきて、計測ツールの導入やgit運用なども問題なくできるようになりました。 チューニングに関しては主に以下のところを重点的に見ました。
Indexを貼る N+1を解消する 無駄なDBへのアクセスを減らす(Redisのようなオンメモリでデータを持たせるなどの解決策) バルクインサート DBサーバーとAppサーバーを分ける。 これらの典型的な実装や設定は調べながら練習していきました。Indexを貼ることやDBとAppを分けることは設定方法が簡単ではあったのですぐにできるようにはなりましたが、N+1の解決やRedisでデータをもたせるようにするにはGoの知識や実装力が必要だったのでかなり苦労しました。(少なくとも自分はかなり苦労しました。。。)
本番の流れ 起床試験は全員合格できました。9時半からYouTubeのライブ放送を見て、isuconの雰囲気を楽しんでいました。(サービスの紹介動画が毎回面白くて好きです。)
コンテスト自体は10:00から開始でした。
10:16 環境構築、初回ベンチマーク-&amp;gt;3379点 10時にコンテストが開始して、自分は環境構築(ssh接続やMakefile編集)、他２人がマニュアルを読んだり、DBのスキーマを覗いたりでそれぞれ作業しました。10:40ごろにひとまずMakefileの編集が終わり、ベンチマークも正常に回せることを確認。githubにpushし、alpやslow-query,マニュアルの内容などを共有して、各自でチューニング作業を行いました。
12:31 インデックスを貼る-&amp;gt;4172点(auaua) 初動でのalpやslow-queryを見て、必要そうなところにインデックスを貼ってくれました。
13:44 Redisでアイコン画像をキャッシュ-&amp;gt;9,316(kentakunkentakun) アイコンの取得に時間がかかっていることをalpで確認できたので、早い段階でRedisでキャッシュさせようという方針が立ちました。画像の枚数も見た限りだと100枚程度だったので、おそらくメモリは足りるだろうということでRedisのimportやキャッシュ処理の実装を彼にやってもらいました。
15:22 インデックス追加-&amp;gt;11469点(auaua,kentakunkentakun) 中盤からボトルネックになりだしたライブストリーム関連のDBにインデックスを貼ってくれました。
16:41 getUserStatisticsにあるN+1を部分的に改善-&amp;gt;13978(saity) 15:00あたりでユーザ配信統計情報とライブ配信統計情報の２つの処理がボトルネックになっており、そのうちのユーザ配信統計情報の方にN+1が複数あったのを確認したのでその改善をしました。Go言語の実装力が低いせいですべてのN+1を解決できませんでしたが、結果的にスコアは少し伸びました。
17:29 DBサーバーとAppサーバーの分割-&amp;gt;21794(auaua,saity) 17:00時点でGo言語実装での改善は終わらせることにして、DBとAppの分割を共同で行いました。
17:53 log出力の停止-&amp;gt;22558 nginxのaccess_logとslow-queryのログを吐き出さないようにしました。
17:58 最終ベンチ -&amp;gt;22284 その他の改善 13:41 fillLivestreamResponseのN+1改善(saity) 序盤でボトルネックになるエンドポイントの関数中にN+1の処理が入っていたので改善しました。しかし、実装した後でボトルネックがアイコン画像の取得であることを知ったため、どの程度スコア向上に寄与しているかが不明でした。Redisキャッシュの改善をマージしてベンチを回す時に、ここの改善も一緒に反映された可能性があります。
17:54 ReactionsやStatistics周りのデータをオンメモリで持たせる。(kentakunkentakun) 詳しいことは聞いてませんが、ライブ配信の統計情報のデータをRedisで持たせて、煩雑な処理を改善しようとしていました。終了5分前ぐらいにベンチマークを回しましたが、failedになってしまったので、変更を反映させることができませんでした。
結果 スコアのみの順位⇨ 最終結果⇨ 結果は570位中108位という結果でした。ですが、追試も含めたらそもそもランキング外のようなものなので複雑な気分です。実は今回のコンテストでは、Indexを貼るにあたってベンチマークを回す前にインデックスを正常に設定するためにDBの初期化を行うという追加の処理が必要となっていました。再起動試験の失敗はその処理のし忘れが原因でした。これは単純に全員そこまで気が回らなかったというのが原因ではあります。終了３分前ぐらいにリマインドタイマーを設定するぐらいの対策をするべきでした。</description>
      
    </item>
    
  </channel>
</rss>
