Sagittariusには(net server)というライブラリがあって、それを使うと割と簡単にノンブロッキングなサーバーが書けたりする。このライブラリは(paella)の基盤になっていたりするので、個人的に書くWebアプリは意識の外側にくらいの位置ではあるが使われていることになる。そんなライブラリ+news-reader.nlで使われているということもあってそれなりに安定していると盲信していたのだが、実はそんなことなかったという話。
ことの発端は今書いているWebアプリがある程度走るとCPUを100%使いだすというもの。これが続くと嫌だなぁと思って、モニター機能をつけてみたところ、どうも挙動が怪しい。スレッドを50個作っているのに動いているように見えるのは一つしかない。スレッドにソケットを割り当てるために持っている優先度付きキューもなぜか要素が一つしかない。
結論を言うと3つのバグが複合的に働いてCPU使用率を100%にしていた。
【バグ1】
優先度付きキューの比較ロジックがおかしかった。スレッドにソケットを割り当てるようなので、スレッドIDとそのスレッドが保持しているソケットの数をペアにして持っていたのだが、その比較がおかしく、ソケットの数が同一であれば同一の要素とみなしてしまっていた。そうすると初期化時にすべての要素が同一とみなされかつ、追加時に同一要素を削除しているので結果的に一つにしかなっていなかった。
修正はこんな感じ:https://bitbucket.org/ktakashi/sagittarius-scheme/commits/c52fab262da092a1ca676c9e067798a4c60f610f?at=default
【バグ2】
優先度付きキューに要素を足すときにサイズの取得がロック外だったため最大値を設定しているにも関わらずキューのサイズが増えていた。これ自体はCPU使用率100%に直接関係はないのだが、モニターを作ったときに予定外の値が渡されるので気付いた。
修正はこんな感じ:https://bitbucket.org/ktakashi/sagittarius-scheme/commits/a96c51bd93076ddb5454060b82cc1ed087c681f1?at=default
【バグ3】
Paellaが特定の場合にソケットを閉じていなかった。データ読み取りすると空データを返すソケットを閉じていなかった。これが無限ループを起こしてCPU使用率100%になっていた。Linux上でのみ起きるので気付きにくかったというのはある(言い訳)
修正はソケットを閉じるだけ。
実用に耐えているからといってバグがないわけではないという話である。しかし、今までスレッド1個しか働いてなかったのか、ソケット自体は複数個扱えてたのが災いして気付かんかった。
No comments:
Post a Comment