まめに録画する根性はない。DVDを買い続ける金もない。 だからレンタルビデオで行こう!

[雑記] ランク情報の欠落

放送中アニメの人気ランキングについて。
時間がないのでいちいち書いてませんが随時改良を重ねています。
特に先月と先々月には内部処理にかなり大幅な改良を行いました。
見た目的にはリリース情報がないものをわかるようにしたぐらいかな。
レンタルは有るけどセルが出てないのもわかるようにしました。
どちらも前から気にはなってたので大幅改修のついでに実装しました。

内部処理の大幅な改良については使う側はあまり関係がないですが
参考になる人がいるかもしれないのでメモがわりに書いておきます。


改良点の1つ目はメモリーリークを無くしたこと。
ランキング情報は30分毎にデータを取得して更新してるわけですが、
この処理で大量にメモリーリークしてる事に今さらに気づきました(汗)。
300~500Mbyteぐらい大量にメモリー消費してるのは知っていたけど、
大量にデータを取得して加工してるからそーいうもんだと思ってました。
でもメモリー使用量が増えないはずのところで増えたので気づきました。

XMLを解析してるとこでDOMツリーを毎回明示的に破棄してなかったので、
Amazonから取得したデータのDOMツリーが全てメモリーに残ってたという。
一度に150回ぐらいデータを取得してるのでえらい事になってたわけです。
そーいや動画配信サービスナビで全く同じところでハマってたなと……
XMLパースのモジュールは既存のモノなので問題に思い至らなかったよ。
なんか上手いことデータを破棄してくれると勝手に思い込んでたみたい。
てゆーかネットのサンプルソースでツリーを破棄してるの見た事ないぞ。
まぁ、PerlのCGIはリクエスト処理して結果を返せばプロセス終了だから
多少のメモリーリークなんてほとんど問題にはならないとは言えるけど。
150回もXMLをパースするのが尋常じゃないだけで。

と言うわけで毎回DOMツリーを破棄してメモリーリークを無くしました。
結果としてメモリー使用量が数10MByteまで減りました。
そして更新プロセスが途中で勝手に打ち切られる事も無くなりました。
プロセスが止められてたのは時間が長すぎたせいじゃなかったんだ……
長すぎるんだと思って処理を分割したのは無駄な努力だったのねん(泣)。
まぁ、処理を分割する事でメモリーリーク量も抑えられてたわけですが。
この改修作業をやった10月頃には毎日のように更新が止められていたので
改修によってそれが無くなったのが予想外のメリットだったすね。
しかし平穏な更新処理は長くは続かなかったのでした。
Amazonから新たな不具合という刺客が!(詳しくは後述)


改良の2つ目はデータ更新処理の最適化。
ランキング更新処理で取得したデータを過去のランクと合成してますが
この時にデータの検索処理を最適化してみたら驚くほど速くなりました。
まぁ、最適化以前は単にリストを順にチェックしてただけですが。
これを検索対象のリストを予めASINをキーにしてハッシュに入れてみた。
そしたら10秒以上かかってたリスト合成処理が1秒かからなくなった……
書き方次第でパフォーマンスが天と地ほども違うといういい例ですね(汗)。

実は処理の非効率さには前から気づいてはいたのです。
でもなし崩しで拡張を重ねたコードなので構造が凄く汚くなってまして。
何しろ最初のバージョンには非同期のデータ更新処理すら無かったので。
なので内部構造のリファクタリングを先んじてやってたわけです。
そしてやっとデータ処理の非効率な箇所に手を入れる事ができたわけで。
メモリーリークもその作業の過程で気づいたようなもんです。


ランキング更新処理が210秒から200秒になっても大差はなかったりする。
(Amzaonと通信してる部分で200~250秒ほどかかってます)
ぶっちゃけ今まで放置してたのも実害が無かったからにほかないわけで。
手間かけてまで処理を最適化したのには切羽詰った事情が有りました。
それは、今現在サーバーリソースをかなり消費してるという事情です。
レンタルサーバーの負荷が追い出されかねない状況に近づいてるのです。
サーバーログによると放送中アニメの人気ランキングのスクリプトは
いつのまにやら1日4000アクセス(500ユニーク)ぐらい行ってるご様子。
しばらく安定してたけどここ数ヶ月でアクセスが倍増してるみたい。

ちなみにブログパーツのアクセス数は一日20000アクセスぐらい。
ブログパーツも含めた1日の転送量が先月の平均で1GByteに達してます
500Mbyteぐらいで数ヶ月安定したのにここ最近また上昇し始めた模様。
先月のピークだと2GByte近くまで行ってる日があります……
ライトコースだと転送量3Gbyteぐらいが上限の目安なのでそろそろヤバイ。
まぁ、月100円コースでこんだけ使えれば十分だと思いますが。

サーバーの負荷は転送量とは別にCPU使用時間というのが有ります。
恐らく動的生成のスクリプト(CGI)が占有してる時間だと思われます。
ものすごい転送量になってるブログパーツは固定したファイルなので
こちらの負荷はほぼアニメランキングがかけてると思われるわけで。
(アニメ動画配信サービスナビは問題になるほどアクセスが無い)
そしてCPU使用時間も既に予断を許さないレベルに達してたのでした。
いずれは上位プランに引っ越すにしても多少は足掻いてみようかなと。
更新処理の効率化はつまりそーいう意図で実行されました。


改良の3つ目は表示のキャッシュ処理。
今まではリクエストが有るたびにランキングページを生成してましたが、
一度生成したページをデータが更新されない限り流用するようにしました。
これも以前からずっと考えてたのだけどどう実装するか悩んでたわけです。
データ更新時にアクセスの多いページを一緒にに生成してしまうかとか。
とりあえずリクエスト内容で判断して必要なら生成する仕様にしました。
これならキャッシュ生成したけど実際には使わないみたいにならないし、
アクセスの多いページなら確実にキャッシュが効くはずなので。

最適化とキャッシュ処理でだいたい3割ぐらい負荷が軽減されました。
これで上位プランへの引っ越しが少し先延ばしできればいいけど。


最後に改良の4つ目。
ここ最近ランキング情報がごっそりと欠落することが頻発してます。
昔から一部のアイテムのランク情報が一時的に欠落する事は有ったけど
ここ最近数100~1000アイテムという大量のランク欠落が発生してます。
この1週間なんか毎日のようにランク情報欠損状態になっています。
※この文章を書いたのは1週間ぐらい前です
履歴のグラフで線が切れてる箇所がランク情報が欠落してるところです。
(作品の履歴でいきなり下に落ちてるのは一番上が欠落してる状態)

さすがにここまで頻発するとアニメランクの信頼に関わるということで
大規模に欠落する時は一つ前のランク情報を流用するようにしました。
今のところ2回連続して大規模欠落は発生してないので行けるかなと。
お店側で表示されてるランクと微妙にずれてしまう可能性はあるけど、
今までもAPIで返ってくる情報は半分ずつ更新みたいなことが有ったし、
欠損するよりは少し前のランク情報のほうがマシだろうと言うわけで。
(個別にデータが欠落してるのも一定の法則で補完するようにしました)

ちなみに最初はリトライして何とか情報を取れないか考えてました。
しかしリクエストを変えて再度試してもやっぱり取れないようで。
(ある程度時間をあければ取れるかもしれないけどやりようが無い)
どーやらAPI側で持ってるデータからランク情報が欠落してるみたい。
お店側サーバーとのデータのやり取りに不具合が混入してるみたいです。
半分ずつランク情報が更新されてたのも似たような不具合だろうなと。
しかしAmazonは定期的に不具合を混入しないと気がすまないのかね……


もう一つ。これは最近追加した機能ではないけど告知してなかったので。
順位履歴のグラフに一日の平均値(長期)のグラフが追加されてます。
実は1週間の詳細順位のグラフを作った時に一緒に実装してたのですが、
グラフを表示してみたら平均値の計算が間違ってたのが発覚しまして(爆)。
1週間のグラフは1週間すれば入れ替わるので間違いもすぐ消えるけど
長期グラフは半年ぐらい残るので間違ったデータもずっと残ってしまう。
さすがにそれはまずいとデータを一度全消去して最初からやり直しました。
そしてグラフはデータがある程度たまってから表示するようにしました。
最初から長期のグラフが見れたのは確か今年の4月組からだったはず。

この長期の変動グラフはいろんな情報が読み取れてとても面白いです。
「STAR DRIVER」なんか放送日に跳ね上がりずるずる落ちていくので
1週間周期で尖った山ができる実にわかりやすいグラフになってたり。
(放送周期の上下がここまで極端なグラフはあまりない)
ヨスガノソラは1話と4話のあたりでものすごく順位が上がってるとか。
自分作っといてなんだけどこれはランクそのもの以来のヒットだと思う。
見たことない人は試しに眺めてみてください。
(ランク変動の)範囲の右にある「→」で見れます。

コメント

コメントの投稿

管理者にだけ表示を許可する

記事への反論は非公開を指定しても公開します
公開して欲しくなければメールで送って下さい

※コメント・トラックバックについてのおことわり

トラックバック

トラックバックURLはこちら
http://navido.blog12.fc2.com/tb.php/1353-0772994f