Skip to content

Instantly share code, notes, and snippets.

@mshibuya
Created May 31, 2013 09:09
Show Gist options
  • Save mshibuya/5683783 to your computer and use it in GitHub Desktop.
Save mshibuya/5683783 to your computer and use it in GitHub Desktop.
5/31 Ruby会議メモ

Ruby会議 5/31

High Performance Rails

@mirakui / CookPad

  • 1000 models
  • 300 controllers
  • 2000 routes

CookPadでは: 200msより遅い = 改善されるべき遅いページ

レスポンスタイム
  • Completed time (Railsの実行時間)
  • X-Runtime (Rackの実行時間)

Railsは遅い?

パフォーマンスを上げるための大前提

Rubyに処理をさせない。 静的ファイルはUnicornで配らない。

通常の構成

Nginx → Unicorn

CookPadの構成

Apache → Varnish → Nginx → Unicorn

Railsのパフォーマンスボトルネック

  • ARのオブジェクト作成
    • クエリ以外にも時間がかかる
    • オーバーヘッド・メモリ消費が多い
  • ルーティング
    • ヘルパー
      • 速い → hello_index_url
      • 100倍遅い!→ controller: 'hello', action: 'index'
  • テンプレート
    • コンパイル時間は重要ではない。一回しか実行されないから
    • レンダリング時間が重要 今のところSlim < ERB < Hamlの順で遅い
  • Unicorn GC.disable
    • 止めといてまとめて実行

slow queryとどう戦うか

http://github.com/cookpad/arproxy

スロークエリを捕まえてfluentd MongoDBに貯めておく

パフォーマンスチューニングのトレードオフ

Developers 対 Users, Servers

Q&A

ARインスタンス生成が遅いことへの対策は?

  • find_in_batches
  • AR#crack
  • mysql2を直接叩く

遅い部分をどう見つけるか?

  • newrelic
  • munin
  • パフォーマンスに影響があったらスロークエリをチェック

未然に劣化を防ぐパフォーマンス検証用のテスト環境などはある?

  • 次にデプロイされるコードをステージングで動かして、チェックできるツールがある

ARスキーマ上の注意はある?

  • serializeは使ってないのでよくわからない

計測ツール

  • rubyprof, kcachegrind ←詳しすぎるのでおすすめできない。「to_sが重いよね」とかいう結果になったり
  • ActiveSupport::Benchmark

===

JenkinsとPullRequestでgem依存関係を継続的に更新する

@kyanny

  • 継続が大事!
  • ちょっとずつ改善する

gemの基礎

  • rubygems
  • bundler

gemは日々更新されている

更新しなくてもいいんじゃ?

そんなことはない!なぜなら

  • たくさんのひとが改善している成果を使わない手はない!
  • 古いバージョンに縛られてその制約を回避していくのは非生産的
  • アップデートが後手にまわるとどんどんたまっていく
  • こまめにやるべき

継続的にgem依存関係を更新していくことの問題

  • やる気だけでは続かない
  • 日々の作業と相容れない
  • email通知だと義務感にかける

解決法

自動化

  • やる気がなくても動く
  • Jenkins
    • Gemfile.lockの更新を自動でコミット

可視化

  • 開発者に判断させるには?
    • Pull Requestを送る
利点
  • 目立つ
  • 開発者の見たさ・マージしたさを逆手に取る
  • Diffを取りやすい
  • 放置できない

傷の浅いうちにgemの振る舞いの変更に追従したい

嬉しい副作用

gemを修正してPull RequestすることでOpen sourceに貢献できる!

まとめ

  • 継続的に依存関係を更新するのは重要
  • でも難しいよね
  • bnudle updateをJenkinsで自動化
  • Pull requestで見える化
  • 改善し続けることは大事!

===

Security is hard

@indirect / CLOUDCITY development

Ruby security releases

多かった

Rails Security releases

これも多かった

CVEって?

  • common vulnerabilities and exposures
  • 権限のある企業が番号をふる
  • CVEデータベース
    • cve.mitre.org
    • nvd.nist.gov

dhh + rails

  • attackを受ける全てだった
  • 多数のgemで構成されている
    • セキュリティホールが入る機会が増える
  • すごく基本的なgemにもsecurity issueがある

どうすべき?

  • 更新は大変
    • 「更新作業してると開発が止まるんでしょ?」
  • 更新 = 保険
  • 更新しなければ、破滅的な結果になる
    • ユーザへの開示
    • 責任
    • 訴訟

更新を行う価値はある!

セキュリティ上の問題をどう報告するか?

  • 企業は開示したがらない
  • 開発者は認めたがらない

なので

セキュリティ報告者に報奨する

Responsible disclosure policy

  • Google
  • facebook
  • github
  • engine yard

自分以外の作るアプリ・ライブラリにバグを見つけたら

公開する前に

  • 自分以外の情報が見れる?
  • 自分以外の人の何かを無効にできる

どちらかに当てはまるなら、責任ある公開を。

一般にその情報を公開する前に作者にコンタクトをとる

一緒に協力。だめなら、自分で直しちゃえ!

あなたのgemにセキュリティ上の問題があったら

  • easy: 直してリリース
  • medium: すでに問題が広まっていたら
    • 一般に公開する前に直してリリース
  • hard: セキュリティ報告者から連絡を受けたら
    • すぐに、常にコンタクトを取る
    • 見通しを伝える
    • 直して、リリースして、感謝
連絡先をちゃんと示す
  • 個人なら
    • gemspec email
    • github email
  • チームなら
    • security address
    • PGP key
    • disclosure policy
エコシステム

http://bit.ly/ruby-sec-ann

Q&A

#####古いバージョンの面倒は? Railsみたいにバックポートしてあげるのがいいよね

#####リリースにあたっては セキュリティパッチはセキュリティーリリースだけにしましょう。

#####一般に公開されてしまったら ASAPで直しましょう

===

Ruby on your Rails

@a_matsuda

go west

前進し続ける

Frameworkに実装するには

  • 適切なユースケース
  • 適切なapi
  • 適切な実装

が必要

WHERE NOT, WHERE LIKE

却下された

where.not where.like where.not_like

where.notだけRails4に入った

教訓

  • ideaをgemに
  • Jeremyはすごい
  • DHHはもっとすごい
  • AR4にはwhere.notが入った!

コントローラのactionがrubyっぽくない

アクションのparamsを引数で受け取る

http://github.com/asakusa_rb/action_args

ヘルパーは醜いし、モデルが肥大化しちゃう

デコレーターを使おう

http://github.com/amatsuda/active_decorator

ブラウザで入力が検証できるけど、Railsでは使えないの?

Validationをdryに

http://github.com/amatsuda/html5_validators

結論

  • Edgeをつかおう
  • 注意深く、批判的に
  • 自分の問題を解決
  • Pull Requestを送ろう!

===

Rubyの並行性

josevalim

なんで並行性?

4コア → 4 Rails Server

50コア → ?

50コアCPUがそんな高くなく入手可能に

現在の問題点

thread-safeへの課題

  • ドメインロジックで起こる問題
    • 例:クラス変数
    • shared mutable state(global)
    • クラス変数をリクエスト中で変更しないで!
  • Ruby coreで起こる問題
    • Ruby実装ごとにThread safetyが変わる
    • 例:ActionController::Base
      • 全controllerが同じinstanceを共有
      • YARVではOK, JRuby/Rubiniusではthread unsafe
      • でも、GVLは他のコードを止めちゃうのでよくない
でも、thread-safe対応は
  • ドメインロジックに関係ない → メンテ性を損ねる
  • YARVのパフォーマンスを損ねる
  • 開発者がうれしくない

もっといい抽象化が必要!

他の言語から学ぶ

Java

  • 並行性を保証したクラス群
  • 数は多すぎ

なので

  • Hashで言えばConcurrentHashを作っては?
  • ↑あんまよくないと思う。なぜなら
  • Hashは要素数によって内部構造を変える

すべてを支配する、単一のクラスが必要

提案1

Hash#concurrent_read, Hash#concurrent_writeみたいなの。

提案2

  • AtomicReferenceをthread.rbに追加
  • atomic_accessor
  • compare_and_swap
    • lock freeなデータ構造に必要

Go

  • 共有メモリをつかって通信しない。
  • 通信によって共有メモリを作る。
  • Channels
  • Goroutines
    • どっちもfirst-class

じゃあ、Rubyでは

  • Queue
  • SizedQueue

提案3

Queueを強化する

Erlang

  • 軽量スレッドがある

提案4

軽量なprimitiveを提供する

結論

  • semanticsの違いが、並行性への対応を難しくする
  • 並行性への理解が足りない。並行的に考えるよう教育が必要!

===

ConcernでRailsアプリをきれいに

http://gist.github.com/moro/5652724

背景

  • Railsが現実世界の、複雑な問題に解決に適用されつつある
  • Skinny controllers, Fat models
  • モデルが肥大化!

ActiveSupport::Concern

  • Rubyのモジュールを拡張したもの
  • extend ActiveSupport::Concern

なにがいいの?

  • インスタンスメソッド
  • クラスメソッド
  • 宣言的メソッド

をひとまとめに扱っていることを規約で示せる!

どう使えばいいか

modelの共通の振る舞いに名前をつけて切り出す

  • Taggable
  • Commentable
  • Censorable
  • UsersResource

さらにリファクタリングを進めるには

  • Concernで切り出したモジュールはglueに留める
  • ロジックはPlain old Rubyなクラスに切り出す
  • ベースクラスにあんまり影響を与えない
  • 疎結合

ベースクラスによって処理を分けるには?

あんまり決め手っぽい方法はない

  • ベタに条件分岐
  • baseクラス側にメソッドを生やす

対策として

Refinements

  • Ruby2.0で追加された
  • Concernと相性がいい

まとめ

  • ActiveSupport::Concernはアプリをきれいにするのに役に立つ
  • ロジックは別途書く。Concernをでっかくしない

===

Fat Modelをパターンでリファクタリングする

Bryan Helmkamp

https://github.com/codeclimate/refactoring-fat-models

RailsはOOPなシステムを作る手段を提供してくれない

ActiveRecord pattern

  • 利点:単純さ
  • 欠点:DBスキーマに縛られる

God Objects

解決法

  • ☓ Skinny Controller, Fat Model
  • ○ Skinny Controller, Skinny Model

Anti-pattern

mix-inに分けちゃうのはよくない!

  • mix-inは継承
  • ゴミ捨て場
  • オブジェクトを取り出すのが困難

6つのパターン

  1. Value Objects
  2. Service Objects
  3. Form Objects
  4. Query Objects
  5. View Objects
  6. Policy Objects

まとめ

Underengineering / Overengineering

Rails appはUnder engineeringになりがち

複雑さを制御する!

===

Ruby 2.0のGC

nari

http://gist.github.com/authorNari/3812118

GCって?

  • 死んだオブジェクトを回収する
    • 二度と参照されなくなった
  • Rootsからたどれなくなった = 死んだ

CRubyのGC

  • Mark&Sweep
  • Mark Phase
    • 到達可能なオブジェクトをマーク
  • Sweep Phase
    • マークされていないオブジェクトを回収

改善

非再帰マーキング

今まで

  • クヌースのアルゴリズム
    • Marking buffer
    • それもいっぱいになったら、全部再スキャン
  • 問題
    • リスキャンはおそい
    • stack overflowのチェックが完全ではない
      • Fiberを使っている時なんか落ちたり

マシンスタックを使わずに、自前のスタックを持ってマーキング

  • 足りなくなったらallocate
  • 利点
    • 複雑なスタックチェックがなくせた
    • SEGVしない
  • 欠点
    • 本当に速いの?
    • GC中にstack chunkを割り当てなきゃいけないかも

1.9.3にもbackport済み

ビットマップマーキング

  • マークビットを一箇所に集める
  • Copy on writeとの親和性高
実装

特定のオブジェクトがどのビットなのかをどう見つける?

  • 16KB区切りのブロックで確保
  • 0x3fffと&して、heapのヘッダーを見つける
ベンチマーク
  • グラフ

まとめ

  • 非再帰マーキングとBitmapマーキングがRuby2.0で実装されたよ!
  • RgenGCはcool!

===

2013 CRuby committers紹介

@nagachika

コミュニティの話

最近のRuby core開発の動向

  • 開発スピード
    • 35%ほど1日あたりのコミット数増加
  • 2.1.0
  • 1.9.3
    • メンテは続く

CRuby committer紹介

===

LT

コールセンターを作る

  • 既存のを置き換える
    • agentを効率的に
    • コストを減らす

他文化を紹介すること

  • 句会
  • 文化をシステムとして紹介する
  • I18nを使っておこう!

Programming Glitch

  • 画像をこわす
  • s/a/b/g

Ruby skillを改善するのにFlash cardを使う

  • Rubyを学ぶのに、全部はなかなか頭に入らない
  • 本を読んでいて、カードに気になる内容のQ&Aを書く
  • http://ankisrs.net/

DeNAのログ戦略

  • fluentd
  • 手作業では管理できない
  • haikanko

RSpecのテストコードジェネレータ

  • rspec-kickstarter

3DCG-ARTSの紹介

FlawDetecter

  • 単純バグを検出する静的解析ツール
  • 15のOSSに試して、2つを見つける
  • 3パターンしかない

ScreenX

台湾のRubyコミュニティ

  • ruby.tw
  • RubyConf Taiwan
  • 戦おう。ここがオレたちの世界だ

Sinatraで作る画像リサイズエンジン

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment