mikutterの最新の情報は、mikutter blogに引っ越しました。

2011年3月20日日曜日

#mikutter 0.0.2.12

ピャアアアアアアアアアアwwwwwwww今週リリースしない予定だったけど調子でないから休憩中にバグとか直してたらつい時間をかけすぎてリリースしちゃうwwwwwwww楽しいfixがwwwwwwポポポポーンwwwwwww

よかったこと
mikutterのアイコン完成
実はsoramame_bsclにアイコン作るように去年のはじめにお願いしてて、半年放置されたからヤツの落書きを勝手にアイコンにしてただけだったんですwwwwやっとだよwwwwウェブページのファビコンにもしたよ!やったねたえちゃん!

よくなかったこと
キャッシュがスレッドセーフじゃなかった
ギャアアアアアアアwwwww俺SUGEEEEEEEEEEwwwwwwww

特定条件を満たすつぶやきをふぁぼると落ちる
ひでぇぇぇぇwwwwwww

リスト取得するときにたまに落ちてた
ウワアアアアアアアアアアwwwwwwwもうかくのめんどくせえよおおおおおwwwwww

0.0.2.10以前を使ってる人は、ここのところ全く機能追加できてないお陰で安定性上がってるっぽいので是非バージョンアップしましょう。どうせおちるんだろうけどねwwwwうわあああ死にたくないよおおおwwwwwwwww

2011年3月13日日曜日

#mikutter 0.0.2.11

  • 不具合修正
    • ruby 1.9.2を使用している場合、頻繁にSegmentation Faultが発生していた
      • →rubyか周辺ライブラリのバグを踏んでいたよう
    • notifyのリツイート通知の時に、原文が2回表示されていた
  • 最適化
    • アイコン画像プリフェッチ
殆ど何も変更できてないわけだけれど、これが0.0.3.0になるんじゃないかな、落ちないので。
まあリリースして1日以内にクラッシュするような不具合が見つかるというのを10週連続でやってるんだけどね!

あとレンダリング高速化しようとしてやっぱりやめました。もうちょっと時間をかけて大規模なのをやります今度。

それから、mikutterのサイトのリリースノートやめてこっちにしますんで!だってあのリリースノートRSSにも対応してないただのHTMLなんですもの…(´・ω・`)

2011年3月6日日曜日

#mikutter 0.0.2.10

リリースしました。出先からなので適当に

○プロフィールを開いてすぐに閉じる
とクラッシュする
○Mumbleオブジェクト作成中に落ち ることがある

うけるヾ(@⌒ー⌒@)ノまじこれだけ

あと少しパフォーマンスを上げようとして、ああ、今回もだめだったよ。

そろそろ根本的な解決をしていきたい。mikutterのコードも当社比リファクタリングが進みきれいになったので、マルチスレッドでGtkのレンダリングをしても死なない気がしてきた!ちょっと頑張って見るかな。

あと1.9.2で特定リビジョンがうごかんと言われて試したら、うちでは全バージョンが動かなかった!どうしてこうなった!一応サポートしてるのは1.9.1なんだけど、これもかっこ悪いのでぽちぽちなおしますね…

いつ2次元に旅立っても大丈夫なように@Phenomerさんにコミッタになってもらいました!だけど今クールいくといろいろひどいことされそうなのでもう少し娑婆で頑張る!

2011年3月2日水曜日

streamingプラグインの最適化

streamingプラグインはuserstreamを実現するためだけのプラグイン。(core/addon/streaming.rb)

UserStreamは大量のデータが落ちてくることがしばしばあり、フォローが多いと秒間に数個からヘタをすると数十個のイベントが落ちてくることもあるかも知れない。
(ここでつぶやきではなくイベントと言ってるのは、フォロー関係の変更やDM、favなども落ちてくるので)
mikutterでは、正確にはわからないが、まあフォローが1000を超えていたら絶対に動かないだろう。これは、流速が処理速度を超えるから。
そういう極端に速い環境を切り捨てるのは仕方ないにせよ、全員が定期的に呟いている訳でもないので毎週火曜夜に流速が極端に速くなるということもあるかもしれない。なので、できるだけ対策をしてみようと思った。

これの33行目くらいから変な魔術を使ってる。

# イベントを定義するためメソッド
    def self.define_event(event_name)
      type_strict event_name => tcor(Symbol, String)
      queue = Queue.new
      service = nil
      Thread.new{
        sleep(1) while not service
        loop{
          datum = queue.pop
          yield(service, datum)
          sleep(1) } }
      define_method("event_#{event_name}"){ |json|
        type_strict json => tcor(Array, Hash)
        service ||= @service
        queue << json } end

    # favられイベントの定義
    define_event(:favorite) do |service, json|
      by = service.__send__(:parse_json, json['source'], :user_show)
      to = service.__send__(:parse_json, json['target_object'], :status_show)
      if(by.respond_to?(:first) and to.respond_to?(:first) and to.first.respond_to?(:add_favorited_by))
        to.first.add_favorited_by(by.first, Time.parse(json['created_at'])) end end

event_favoriteメソッドがfavられた時に呼ばれる。こいつが実際のイベントをよんでいるんだけど、いちいちdefine_eventを使って定義している。
このdefine_eventで定義されるevent_favoriteは、Queueに引数をそのまま積んでおしまい。実際には、定義されたと同時に作られた別のスレッドがイベントの処理をする。
これによって、イベント発行にだらだらと時間を使ったりせず、効率的にイベントを発行できるというわけ。
・・・ではなくて、見ていただければわかるとおり、1つキューを消化するごとにsleep(1)を実行しています。
なので、たとえば同時に100favされたとすると、普通の実装だと死ぬほどイベントを発行して、効果音がけたたましく鳴り響いてTLの更新がしばらくおっつかなくなるんですが、この実装によって、最初の1favは即時、残りは99秒かけて1秒間に1つづつイベントが実行される。これによってイベントの実行が遅れる場合が出てくるが、乱発されない限り目立った遅延は起こらない。1つづつしかイベントが発生しないので、処理もすぐに終わるからたいした負荷もかからない。もちろん、フォローなどについても同様。

唯一の例外はつぶやき受信関連。これだけはちょっと違って(詳しくはソースみてくださいそんなにありがたいものじゃないが)、つぶやき関連のイベントは、1回のイベントにいくつでもつぶやきを持たせることができる。なので、1回のループで、キューに溜っているイベントを全て取り出して、一気にイベントを発生させる。
これによって、1秒間に大量のつぶやきを処理する可能性があるけれど、実はイベントの発行って結構非効率なので、10イベンtの発行するよりも1イベントで10ツイートを処理するほうがはるかに経済的。ていうかそんなのが頻繁に起こるならどのみちmikutterつかえない

重要なのは、同じイベントは1秒に1回しか発生しないようになった、ということ。どんな速度でイベントが発生しても、ここでイベントの流量が制限されるようになるわけ。これによって、例えば1分間に100favとかされたときにフリーズすることがなくなりました。

今後の展望(というか実験中のこと)としては、GUIイベントを処理している時など、今やったらユーザの操作に影響が出るぞっていう時にはイベントの発行をさらに1秒遅らせるというの。ウィンドウが完全に応答なしになってるのに次々イベントほりこんでもしゃーないでしょ、という話。TL速い時に起動が数秒遅くなってるんですが、これは起動直後にウィンドウに夥しい量のつぶやきが放り込まれて固まってる間にたくさんイベントが発生しているからに他ならないんですよ。

一方、本当に重くしてる原因は他にあると思うので、そっちを潰すのが先かなぁとも。やはり動きが良いのは良いことです。