strace for perl mongers
DESCRIPTION
YAPC::Asia 2014の発表スライドです。TRANSCRIPT
![Page 1: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/1.jpg)
strace for PerlMongers
zentooo @ DeNA
![Page 2: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/2.jpg)
自己紹介
![Page 3: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/3.jpg)
@zentoo or @zentooo
![Page 4: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/4.jpg)
「愛と勇気と缶ビール」
![Page 5: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/5.jpg)
モバゲーオープンプラットフォーム
![Page 6: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/6.jpg)
元・落語研究部
![Page 7: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/7.jpg)
※トークにオチはありません
![Page 8: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/8.jpg)
straceとはプロセス内で発行されているシステムコールをtraceするため
のツール
![Page 9: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/9.jpg)
その前に、システムコールって何よ?
![Page 10: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/10.jpg)
システムコールは、アプリケーションが叩くOSの "API"
File I/O (open, lseek, write, read, close)Network (socket, bind, listen, accept, connect)Memory (brk, sbrk, mmap)Process (fork, wait, kill)Thread (pthread_create)
![Page 11: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/11.jpg)
システムコールを経由せずPerlでファイルI/Oできるか?
![Page 12: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/12.jpg)
システムコール抜きでPerlで新しいプロセスを作れるか?
![Page 13: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/13.jpg)
システムコール抜きでPerlでネットワークプログラミングが出来るか?
![Page 14: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/14.jpg)
アプリケーションはOSの手の平の上
![Page 15: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/15.jpg)
突然ですが
![Page 16: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/16.jpg)
Q. Webアプリケーションの仕事って何よ?
![Page 17: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/17.jpg)
A. HTTPリクエストを受けてHTTPレスポンスを返すことだ
よ!
![Page 18: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/18.jpg)
Q. HTTPリクエストを受けてHTTPレスポンスを返すってど
ういうことだよ!
![Page 19: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/19.jpg)
A. acceptしてreadしてwriteしてcloseだよバカヤロー!
![Page 20: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/20.jpg)
まあ落ち着け
![Page 21: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/21.jpg)
Webアプリのお仕事1. HTTPリクエストを受ける2. <この間に僕らのドラマがある>
MySQLへのアクセスmemcachedへのアクセス(データの整形、logの書き込みetc)
3. </この間に僕らのドラマがある>4. HTTPレスポンスを返す
![Page 22: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/22.jpg)
システムコール語に翻訳すると...1. int fd = accept(...); // リクエスト受けて2. read(fd, ...); // リクエストの内容読んで3. <この間に僕らのドラマがある>
socket, connect, write, read, closeopen, write, read, close
4. </この間に僕らのドラマがある>5. write(fd, ...); // レスポンス返す
![Page 23: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/23.jpg)
さらに省略すると1. int fd = accept(...); // リクエスト受けて2. read(fd, ...); // リクエストの内容読んで3. <僕らのドラマ />4. write(fd, ...); // レスポンス返す
![Page 24: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/24.jpg)
DEMO #1 - just to strace
![Page 25: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/25.jpg)
straceを読む時のキホン (1)↓システムコール名 返り値↓read(5, "GET / HTTP/1.0\r\nHost: xxx-xxxxxx"..., 131072) = 308 ↑引数(バッファなどの場合はよしなに展開される)
![Page 26: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/26.jpg)
straceを読む時のキホン (2)fd (ファイルディスクリプタ) に注目する
↓コレread(5, "GET / HTTP/1.0\r\nHost: xxx-xxxxxx"..., 131072) = 308
![Page 27: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/27.jpg)
fd (ファイルディスクリプタ)ファイルやネットワークソケットなどを抽象化した構造体へのポインタ(0, 1, 2) = (stdin, stdout, stderr)それ以降は昇順に振られる
![Page 28: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/28.jpg)
fd with fileint fd = open("/tmp/yapc2014", ...);read(fd, buffer);write(fd, buffer);close(fd);
![Page 29: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/29.jpg)
fd with client socketint fd = socket();connect(fd, addr, ...);read(fd, buffer);write(fd, buffer);close(fd);
![Page 30: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/30.jpg)
fdを追うのが捜査の基本ファイルの生存期間
openで返ってきたfdがcloseに渡されるまでクライアントサイドでのソケットの生存期間
socketで返ってきたfdがcloseに渡されるまでサーバサイドにおけるクライアントソケットの生存期間
acceptで返ってきたfdがcloseに渡されるまで
![Page 31: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/31.jpg)
Webアプリのstraceを読む時のキホン// こっからaccept(4, {sa_family=AF_INET, ...)}, [16]) = 5(中略)read(5, "GET / HTTP/1.0\r\nHost: xxx-xxxxxx"..., 131072) = 308(中略)write(5, "HTTP/1.1 200 OK\r\nDate: Sun, 10 A"..., 2218) = 2218// ここまでが一つのリクエスト/レスポンス// keepaliveしてないならここで close
![Page 32: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/32.jpg)
DEMO #2 - strace web app
![Page 33: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/33.jpg)
あくまで基本なので例外もTwiggy, Twiggy::Preforkなどevent-drivenなサーバ(epoll_wait)multi socket listenしてる時のStarlet (select)
![Page 34: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/34.jpg)
Webアプリのお仕事(再掲)だいたいの場合 赤字の部分 で問題になる
HTTPリクエストを受ける<この間に僕らのドラマがある>
MySQLへのアクセスmemcachedへのアクセス(データの整形、logの書き込みetc)
</この間に僕らのドラマがある>HTTPレスポンスを返す
![Page 35: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/35.jpg)
注目ポイント - MySQLsocket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 10fcntl(10, F_SETFL, O_RDONLY) = 0fcntl(10, F_GETFL) = 0x2 (flags O_RDWR)fcntl(10, F_GETFL) = 0x2 (flags O_RDWR)fcntl(10, F_SETFL, O_RDWR|O_NONBLOCK) = 0connect(10, {sa_family=AF_INET, sin_port=htons(3306), sin_addr=inet_addr("10.0.0.1"fcntl(10, F_SETFL, O_RDWR) = 0poll([{fd=10, events=POLLIN|POLLPRI}], 1, 4000) = 1 ([{fd=10, revents=POLLIN}setsockopt(10, SOL_SOCKET, SO_RCVTIMEO, "\2003\341\1\0\0\0\0\0\0\0\0\0\0\0\0"setsockopt(10, SOL_SOCKET, SO_SNDTIMEO, "\2003\341\1\0\0\0\0\0\0\0\0\0\0\0\0"setsockopt(10, SOL_IP, IP_TOS, [8], 4) = 0setsockopt(10, SOL_TCP, TCP_NODELAY, [1], 4) = 0setsockopt(10, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
![Page 36: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/36.jpg)
注目ポイント - memcachedsocket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 8fcntl(8, F_GETFL) = 0x2 (flags O_RDWR)fcntl(8, F_SETFL, O_RDWR|O_NONBLOCK) = 0connect(8, {sa_family=AF_INET, sin_port=htons(11211), sin_addr=inet_addr("10.0.0.1"poll([{fd=8, events=POLLOUT}], 1, 250) = 1 ([{fd=8, revents=POLLOUT}])getsockopt(8, SOL_SOCKET, SO_ERROR, [-511598409602301952], [4]) = 0setsockopt(8, SOL_TCP, TCP_NODELAY, [1], 4) = 0sendmsg(8, {msg_name(0)=NULL, msg_iov(6)=[{"set", 3}, {" csrf_token:", 20}, read(8, 0x59f9f50, 1536) = -1 EAGAIN (Resource temporarily unavailable)poll([{fd=8, events=POLLIN}], 1, 300) = 1 ([{fd=8, revents=POLLIN}])read(8, "STORED\r\n", 1536)
![Page 37: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/37.jpg)
DEMO #3 - strace web appwith DB and memcached
![Page 38: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/38.jpg)
プログラムは思ったとおりに動かない
同じクエリを複数回発射してる思ってたよりcache missしてる無駄にretryしてるTCP Connection使いまわせてないTCP Connectionちゃんと切れてない
![Page 39: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/39.jpg)
実例 #1 - memcached retryproblem
![Page 40: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/40.jpg)
+180msとあるAPIのレスポンスが、リリース後に約180ms劣化50ms or dieなら4回くらい死なないといけないレベル
![Page 41: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/41.jpg)
容疑者Cache::Memcached::Fastのラッパーモジュール
(更新差分があったので)
![Page 42: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/42.jpg)
家宅捜索strace -p $pid -e 'trace=sendmsg'
(Cache::Memcached::Fastがsendmsgを使うのは知っていた)
![Page 43: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/43.jpg)
物証sendmsg(6, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, {" cache_local:", 13}sendmsg(6, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, {" cache_local:", 13}sendmsg(6, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, {" cache_local:", 13}sendmsg(6, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, {" cache_local:", 13}sendmsg(11, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, {" cache_remote1:", sendmsg(11, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, {" cache_remote1:", sendmsg(11, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, {" cache_remote1:", sendmsg(11, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, {" cache_remote1:", sendmsg(11, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, {" cache_remote2:", sendmsg(11, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, {" cache_remote2:", sendmsg(11, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, {" cache_remote2:", sendmsg(11, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, {" cache_remote2:",
![Page 44: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/44.jpg)
ネタばらしラッパーモジュールにretry機能 (maxで3回) が入っていたCache::Memcached::Fastのgetはcache missとその他のエラーを区別できないcache missの度に3回retryしてた
retry間隔は20msec20 msec × 3 (retry) × 3 = 180 msec
そのhit rateはどうなん?という話はありつつもget系はretryしない修正を入れて解決
![Page 45: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/45.jpg)
物証 - with timestamp22:45:34.517703 sendmsg(6, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, {" cache_local:", 22:45:34.537967 sendmsg(6, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, {" cache_local:", 22:45:34.558936 sendmsg(6, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, {" cache_local:", 22:45:34.579275 sendmsg(6, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, {" cache_local:", 22:45:34.587428 sendmsg(11, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, 22:45:34.608296 sendmsg(11, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, 22:45:34.628673 sendmsg(11, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, 22:45:34.649146 sendmsg(11, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, 22:45:35.135129 sendmsg(11, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, 22:45:35.155516 sendmsg(11, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, 22:45:35.176027 sendmsg(11, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3}, 22:45:35.196453 sendmsg(11, {msg_name(0)=NULL, msg_iov(4)=[{"get", 3},
![Page 46: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/46.jpg)
straceしてみると一目瞭然嘘をつかないツールに頼る
![Page 47: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/47.jpg)
嘘をつかないツールstracetcpdumpgdb
![Page 48: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/48.jpg)
嘘をつくもの人の記憶アプリのログ時にはアプリのコード
![Page 49: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/49.jpg)
実例 #2 - accept(2)thundering herd
![Page 50: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/50.jpg)
What is thundering herd"The thundering herd problem occurs when a largenumber of processes waiting for an event are awokenwhen that event occurs, but only one process is able toproceed at a time." - Wikipedia多くのプロセスが特定のトリガーで同時に動き出すが、実際の処理は一個のプロセスでしか行われない (または行われるべき) 時にリソースが無駄になる問題よくあるのはデータのremote cacheがexpireした時に一気にDBへのクエリが走る、とか
![Page 51: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/51.jpg)
accept(2) and prefork server複数プロセスが同時に一つのsocket fdをacceptし、それぞれブロックLinux kernelがよしなにqueueingしてくれるので、リクエストが来た時に起き上がるプロセスは一つだけ
(参考)http://d.hatena.ne.jp/naoya/20070311/1173629378
![Page 52: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/52.jpg)
accept(2) and event-driven/multi-process server複数プロセスが同時に一つのsocket fdをepoll_waitで監視listen socketがread可能 = acceptが可能になった時点でepoll_waitしてる全てのプロセスが起き上がる一つのプロセスがacceptに成功他のプロセスは空振って失敗 (EAGAIN)
![Page 53: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/53.jpg)
accept(2) thundering herdaccept(2)の空振りがプロセス数とリクエスト数の掛け算で発生
loadが上がるvmstatで見ると...
usとsyとcsの値が盛り上がる (50, 50, 100000とか)プロセス間のcontext switch増えすぎが起因かと思われる
![Page 54: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/54.jpg)
DEMO #3 - EAGAIN and againand again
![Page 55: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/55.jpg)
解決策そもそもがevent-drivenなんだしそんなに大量にプロセスあげなくていいよね深淵な理由により100プロセスくらいに (前は300くらいあった)
![Page 56: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/56.jpg)
余談現状のアーキテクチャだと割とどうしようもない気がしている
Monocerosみたいにacceptするプロセスとリクエストを処理するプロセスを完全に分けるとか?
event-drivenとマルチプロセスは食い合せが悪い with PerlIO::AIO (AnyEvent::IOのbackend) とかも割とシングルプロセス前提な実装だったり...
![Page 57: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/57.jpg)
まとめに入ります
![Page 58: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/58.jpg)
straceのわるいところムダな情報がおおい (慣れればどうにでもなるが)たまに起こる系の事象には向いてない (Devel::KYTProfとかでログ出した方がよい?)
![Page 59: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/59.jpg)
straceのよいところ事前設定が不要で、プロセスにattachするだけですぐ見れるWebアプリケーションの気持ちが分かる
![Page 60: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/60.jpg)
straceだと分からないことシステムコールを伴わない純CPUバウンドな無駄な処理アプリケーションでの無駄loop, deep recursion効率の悪いアルゴリズムとか-d NYTProf
トランスポート層以下での問題tcpdumpとかtsharkとかngrepとか使いましょう
![Page 61: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/61.jpg)
straceで分かることリクエスト受けて、レスポンス返すまでのフローデータアクセスの実態実際に何回memcachedからgetしてるか、何回DBみにいってるか実際にcacheされているdata実際に発行しているSELECT文
その他、開発者の予期していない挙動
![Page 62: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/62.jpg)
結び当たり前だけどstraceは万能のツールじゃない使えば明日から捗るとかそんなこともないでも、使い方が分かっていればお手軽・強力Webアプリの気持ちが分かる
![Page 63: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/63.jpg)
参考文献
安いし、電子書籍版(英語しかないけど...)おすすめ日本語版もあるけど1000ページ超、つまり書籍ではなく武器全部読む必要なし、リファレンスとしても便利
↑の本はおすすめだけど、突然読むのは敷居が高いのでとかの方が最初はいいかもし
れない
The Linux Programing Interface
ふつうのLinuxプログラミング
![Page 64: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/64.jpg)
宣伝 (?)Web+DBの2014年10月号に記事(Perl Hackers Hub)を書かせ
て頂くことになりました
![Page 65: strace for Perl Mongers](https://reader033.vdocument.in/reader033/viewer/2022052323/558c02d7d8b42ac25b8b4637/html5/thumbnails/65.jpg)
ご静聴ありがとうございました