Skip to content

Instantly share code, notes, and snippets.

@mshibuya
Created September 22, 2014 04:37
Show Gist options
  • Save mshibuya/b341dbcc45a22db41036 to your computer and use it in GitHub Desktop.
Save mshibuya/b341dbcc45a22db41036 to your computer and use it in GitHub Desktop.
RubyKaigi2014 三日目

RubyKaigi 2014 9/20

おはようRails

パネルディスカッション

Railsをほめよう

  • スタートアップが楽
  • エンジニアを惹きつけるのに役に立った
  • Railsとしてエコシステムがちゃんとしている
  • 新しい人も手順に則って環境構築できる
    • rake setup
  • ActiveRecordがいい
    • Rubyに限らず影響を与えてる
    • ERD書くのと同じ感覚で直接書ける
    • arelが賢い
    • 完成度が高い
    • 生SQLを書くのもいける
    • 裏側のDBを知らなくても業務に入れる

エコシステム

  • テスト
    • コアな部分のみ書いてる
    • カバレッジは高くない
      • リクエストのspecを書いてリファクタリング
    • テストフレームワークに選択肢があって、後付けできる安心感
    • フィクスチャの作り方
      • FactoryGirl
      • Fixtures
      • Fabrication
  • 話が通じやすい
  • gemが入りすぎ
    • 知らなきゃいけないことが多い
  • gemがなんでもrails前提で作られすぎ
    • rails以外を選ぶと苦労する
  • contribute vs monkey patch
    • monkey patchはダメ!
  • 論理削除とかメンテしろ攻撃を受けて辛い
  • ソースを読んでからgemを入れるようにしてる
  • fluentd
    • 時々暴走した
    • 日本での事例が多いからやりやすい
    • アプリケーションまわり
      • 広告ログを集めたり
  • gemを入れるのに抵抗ある
    • 入れたい。入れないのって世界規模でコピペしてるみたいじゃん
    • 消し忘れ
      • 未使用のgemを検出してくれたりするとうれしい

production環境

  • apache / unicorn/ MySQL / Resque / Akamai
  • unicorn/ MySQL / Resque / Whenever
  • EC2 / RDS / ELB / S3 / CloudFront / Capistrano / Jenkinsからデプロイ
  • nginx / unicorn / MySQL / memcache / Resque / AWSとオンプレ併用
  • 国内クラウド / FusionIO / nginx / unicorn / ActiveJob
  • 普通
  • cronつらい
    • レールにのってない
    • バッチに弱い
  • 自分でgemを作って、それを業務に使ってしまう

辛い話

  • ゲームの方々ってRailsじゃなくてよくない?
    • Ruby遅い。Rails遅い
    • バックエンドはRailsである必要はないんだけど、使わないのも辛い
      • 欲しい機能がなかったり
    • 何かベストプラクティスが欲しい
    • レールが敷かれているので、安心感がある
  • Single Page Applicationとか辛い
    • フロントエンドエンジニアが必要
      • nodeでいいじゃん、とか言われる
    • turbolinksがあるからいいじゃん
      • 真っ先に外しちゃう
    • nativeで書いちゃえばいいじゃん
    • このあとSPAについてのセッションあるよ
  • 仕事振るほうとして、最近の若い子たち
    • Railsは業務でやるもの?
    • ネイティブアプリが多い
    • 昔は楽しかった?
  • Railsが「あるべき姿」になりつつある
    • 「なにで作るか」より「何を作るか」
  • Railsが書きたいわけじゃない若い人たちと、どうやってサービスを育てていくか

質問

大規模アプリでJSONをrenderするコストと、ARのinstantiateのコスト

ARのinstantiateのコストは確かにでかい。Pure Rubyでmysql2を直接叩いてる。JSONについては、viewとしてrenderせずserializeして出した方が速い

テストが溜まってきて時間がかかったりする時は?

Engineに切り出してgemごとにテストを行うようにしたので、アプリごとの実行コストは減った

Railsでは分からないことを、新しいエンジニアにどう伝えてる?

コードレビュー。N+1を検出してくれるgem。検知を早くするために、本番クエリを自動でexplain。

ユーザ向けと管理側でモデルを共有したい時どうしてる?

  • モデルだけでリポジトリがあって、symlink
  • アプリをわけてモデルも分けてる
  • API通信で
  • サブアプリとして切り出す
  • Engineで切りだすけどモデルは親のを使う
  • micro services化

Speeding up Rails 4.2

Aaron Patterson(@tenderlove)

Rack

- webサーバのアダプタ
- もう終わり
	- Rack 2.0は発表しない
- 楽じゃない
- the_metal
	- Rack 2.0を試す
- 1.xの問題
	- envが実質グローバル変数
	- ストリーミング対応
- 2.0
	- call(request, response)
	- HTTP/2.0に対応
  • tenderlove/the_metal

Rails 4.2

  • Adequate Record
  • benchmark/ips
    • iteration per second
    • 高いほどいい
    • ブラックボックステスト
    • 線形/定数
    • route tableとlink_toの速さに関係があるか?
      • route表の大きさには関係ない
      • URLの長さに相関がある
    • 線形時間がかかる部分を見つけ、定数化することで高速化!
  • GC.stat
    • オブジェクト割り当てを測る
    • 4.0 → 4.1 → master
      • 19%減った
  • allocation_tracer
    • helperの速度
    • ActiveSupport::SafeBuffer#initializeで時間がかかってる
      • HTMLサニタイズ
      • SafeBufferのオブジェクトを作るのを減らせる
      • 200オブジェクトを削減
  • viewコードの高速化
    • ルールを作ることで、コードを減らせる

まとめ

  • 必要じゃないオブジェクトを消す
  • 一番早いコードとは、空のコード
  • オブジェクトの数を限ることで、コードは単純に
  • 計測、計測、計測して計測!

質問

次の目標は

viewアーキテクチャ、viewコードをもっと早くしたい。まだいろいろゴミとか作ってる。precompileしたらCoW friendlyになるし

SymbolGCのRailsへの影響は?

とっても重要。ただ、古いRubyにも対応しなきゃいけないので、今は生かせない。時間がかかると思う

Practical meta-programming in Application

諸橋さん(@moro)

ゴール

  • Rubyのメタプログラミングに親しむこと
  • メタプログラミングの実用的な使い方を理解すること

メタプログラミングとは

  • 実行時にコード自身を操作するようなコードを書くこと
  • 言語要素
    • class / module
    • objectとinstance変数
    • method
    • 一連の処理
  • Reflection APIs
    • define_method
    • instance_variable_set
    • Rubyには充実している
  • Rubyではとても一般的
  • 特別なものじゃなく、みんな使ってる

メタプログラミングの実際

  • 落とし穴
    • 使いすぎると複雑になる
  • どうしたら実際の現場で使えるようにできる?
    • 問題領域をメタな観点で捉え直して、その先でコードをシンプルにする
      • 例:has_many
        • Association Object
        • 直接Reflectionでくっつけずに、関係を扱う部分をクラスとして切り出している
    • Reflection APIとの薄いラッパーを定義する

実例

  • ミニブログシステム
  • 投稿監視
  • 記事・コメント・画像を監視
  • 重複をくくり出せそう

まとめ

  • 問題をメタな視点から捉え直して、OOPで作る
  • Reflectionからクラスを切り出して、普通につくっておく
  • 普通のプログラミングとメタプログラミングは紙一重
  • メタプログラミングを極限まで試してみるのは楽しいよ

質問

メタプログラミングの失敗

メモリが少ない環境で、ARみたいなカラム名アクセサをつくる機能を作ったら「ARみたいなのにARみたいに使えない!」と大不評だった。

Everything is Broken: A Story of Hope

@1337808

ブラウザにURLを入れると

  • DNS
    • 答えに悪意があってもわからない
  • TCP
  • TLS
    • Random byte
    • 対称暗号、非対称暗号
    • Certificate Authority
      • Online Certificate Status Protocol
        • プライバシー
        • Soft Fail
          • 10秒でタイムアウト
      • OCSP Stapling
        • クライアントに代わりサーバがCAよりOCSPに取得
      • OCSP Must-Staple
        • Hard Fail
    • Premaster Secret
      • Client Key Exchange
    • Heartbleed attack
    • Perfect Forward Secrecy
      • ディフィー・ヘルマン鍵交換
  • nginx
  • rack
  • Railsアプリ

Fluentd Hacking Guide (Fluentd ソースコード完全解説)

瀬尾さん(@sonots)

Fluentdの起動シーケンス・プラグインのロード

  • Fluent::Supervisor#run_configure
    • ディレクティブ - ファイルが有ればrequire - gemも探す
    • plugin
      • initialize
      • configure
    • ディレクティブ
      • pattern
  • Fluent::Supervisor#run_engine
    • start
      • plugin内でthreadを切って、イベントを待ち受ける

input pluginがどうoutput pluginにデータを渡しているか

  • Input plugin
  • emit
  • Engine
  • emit
  • Output plugin
    • すごく重い処理をすると、Input pluginの処理がブロックされてしまう!

BufferedOutput plugin

  • writers
  • buffer
  • ブロックせず、BasicBufferにためていく
  • OutputThreadクラスでthreadを切り、一定時間ごとにtry_flush
    • BufferedOutput#configure
      • threadを作ってる
    • runの中でループ
    • flush interval
  • データが入ってくる速度の方が速いと、queueにたまってく
    • num_threadsを増やす
    • buffer_chunk_limitを増やしてチャンクを大きくする
    • queued_chunk_flush_interval, try_flush_intervalを減らす
    • もともと処理できる量以上はさばけないので、その先のチューニングが大事

まとめ

  • output pluginはblockする
  • BufferedOutput pluginはblockしないが、能力を超えるとつまる
  • 処理性能自体を上げることが大事

質問

BufferedOutput pluginはどういう時使う?

ブロック時間が大きい時。

新しいfluentdではマルチプロセス化?

マルチプロセスになっても、InForwardプラグインはそれぞれのプロセスで起動されるので、この構造がたくさん増えるような感じになる。

The Ruby Challenge

@sikachu

どっちが速いかクイズ

  • sortby rand / shuffle → shuffle
  • split(/,/) / split('.') → split('.')
  • 2回ループ vs 1回で初期化
  • array << n / array += [n] → <<
  • 初期値つきHash / そのつど初期化
  • "<#{str}>" / "<"+str+">" → "<"+str+">"
  • キーワード引数 / Hash
  • tap / tapなし → tapなし
  • fetch / []でデフォルト値 → []
  • stringをto_sym / symbolをto_s → to_s
  • block.call / yield → yield
  • メソッド定義 / attr_reader → attr_reader
  • inject / each_with_object → each_with_object
  • file.write / file.puts → write
  • start_with? / match → start_with?
  • 大文字小文字両方正規表現 / iフラグつきの正規表現 → 大文字小文字両方正規表現
  • デフォルトつきArray#fetch / 別途初期化 → 別途初期化
  • Hash#has_key? / Hash#[] → Hash#[]
  • Array / Hash → Hash
  • inject / ローカル変数 → inject
  • times / while → while

Scaling is hard, let's go server shopping! Or, How we scaled Travis CI, and helped Open Source at the same time.

Josh Kalder

スケーリングとは、金で問題を解決すること

Travisとは

  • open source build
    • 27,000 build per day
    • 79,930 jobs per day
    • 2.93 jobs per build
    • 組み合わせ
  • private repo
    • 1.47 jobs per build
    • 組み合わせはいらない
  • 68以上の専用サーバ

4つのライフステージ

立ち上げ時

  • Rails app
  • Heroku
  • Resque
  • WebSocket
  • VirtualBox
  • RabbitMQ
  • MRI & JRuby

チームを作る

  • 4人で会社を立ち上げた
  • クラウドファンディングでできた

Travis Pro

  • 課金し始める必要があった
  • プライベートリポジトリに課金
    • 需要はあった
    • 山のように機能追加要望
  • 営利ベースでやっていけるようになった
  • 3つの要素
    • 機能
    • バグレポート
    • 最適化
      • 複雑
      • 後回しにできる
  • たくさん利用者が来てる時、どうするか
  • 時間 == 金
  • お金をかける方が、コストが少なく済む時がある
  • dockerの登場
    • 3秒でブートできる

まとめ

  • お金をかけるのがそんなに悪くない時がある
  • お金をかける方が、コストが少なく済む時がある
  • Ruby 2.2が使えるよ
  • Travis Ci Enterprise

Dockerのトレードオフとか

Containerization / Hypervisoration。安全にsudoできない。セキュリティ上の問題

Dockerクライアントをコンテナで走らせたら?

どうやってそう成功するアイディアをえた?

とっても難しい質問。ラッキーだった、としかいえない。コストがペイしないからって諦めるな。

Docker imageに切り替え?

オーケストレーションが必要?プログラムを実行するので、セキュリティはとても重要。

Make your own synchronization mechanism.

関さん

Goの人気が妬ましい

  • Goチャネルがすごい人気
  • RubyのQueueみたいなのがすぐ使える

Rubyのおまけの同期のおさらい

  • 同期
    • 1つ作るといろんな仕組みが作れる
    • 世界の仕組み
    • 俺の同期メカ
  • Rubyの同期メカ
    • 待ち合わせ
      • Monitor類
      • みんなが守らないとうまくいかない
    • 待ち合わせとデータ交換
      • Queue
        • push
          • 容量を超えると止まる
        • pop
          • なにもないと止まる
          • 複数あってもうまくいく
        • 依存関係と待ち合わせを一度に書ける
        • 単なる待ち合わせよりミスしにくい
        • Goのチャネル
          • スレッド間で情報を交換
          • 送信と受信
          • 容量に制限
          • SizedQueueによく似ている
      • TupleSpace

Go風チャネルの作成

  • セルフモチベート
    • よく調べない方がいい
    • 調べると難しさに気付いてしまう
  • 実はSizedQueueとは違った
    • 大きさが0の時は動きが違う
  • 自分で休んでみる
    • 自分でsleepするような実装はたいてい間違ってる
    • Rubyについてる部品を使う
  • カウンティングセマフォ
  • Goチャネルにはselectがある
    • 多元待ち
    • 複数のチャネルのうちどれか1つがreadableになるまでブロック
    • Queue#popはブロックしてしまう
  • 複数Queueでselect
    • Queueベースではだめでは
  • selectも可能にするには
  • TupleSpaceを使う
    • ズル
    • write, take, read
  • ChannelSpace
    • 対象に依存した制御
    • Acotr風通信
  • Monitorで書きなおす
    • やってない
    • みんながすぐ出来る
  • 拡張ライブラリにする
    • やってない

まとめ

  • Goチャネル風な同期メカを書きながら、開発の様子とテクニックを示した
  • 同期メカは同期メカでかけるのでいちいちびっくりしない
  • TupleSpaceは同期メカのプロトタイプにいいので、本を買おう
  • アプリケーションのユースケースで考えるともっといい答えがある

質問

チャネルでチャネルを送るとの、closed?

実装してある。

テストが大変だと思うけど?

自動テストに向かなかったので、irbを2つ上げていろいろ試した。

カウンティングセマフォへのステップアップはどうやって?

MINIXのランデブーが大好きだったので、条件反射みたいに思いついた。

selectはデータを読まないって言ってたけど、readするまでに読まれちゃうのでは?Goは本当にそうなってるの?

その通り。そういう風に書いたやつが悪い。Goは実はそうなってなかった。。select_and_readみたいなのも用意はしてたよ。。

Three Ruby usages - High-level interface, Glue and Embedding - Inside Droonga

須藤さん

分散全文検索エンジン Droonga

  • 分散検索エンジンをたくさんまとめたもの

Rubyの3つの使い方

高レベルインターフェース

  • Pure Rubyist
  • 下のレイヤーの機能をより高レイヤーに提供
  • 使いやすい・便利なAPI
    • Vagrant
    • ActiveRecord

Glue

  • C/C++が書けるRubyist
  • 2パターン
  • 他の言語の機能をRubyから使えるよう
    • 既存の機能を使いたいから
  • 機能と機能をつなげる
  • どう
    • 外部ライブラリを使う(binding)
    • 外部のコマンドを使う
    • 外部のサービスを使う
  • Droongaでは
    • Rroonga
    • Cool.io
  • 重い処理はCでやる
  • メモリ確保は少なく
  • マルチプロセス

Embed

  • C/C++が書けるRubyist
  • アプリケーションに埋め込む
    • 内部エンジン
    • Interface
  • CRuby
    • 全部の機能がある
    • シグナルをトラップしちゃうとか、簡単に組み込めない時がある
  • mruby
    • スレッドごとにインタプリタを持てる
    • 簡単に組み込める
    • 使い物になるの?
  • 大変なところ
    • bindingを書く
    • buildにmrubyを入れるのが大変
    • mruby部分はどうテストする?

まとめ

  • 3つのRubyの使い方
    • High Level Interface
    • Glue
    • Embed
      • 大きな山があるので、本当にやるべきかよく考える
      • 割に合うならやる価値あり

Keynote: Ruby 2.1 in Production

Aman Gupta(@tmm1)

github.com

  • 当時の構成
    • Rails 2.3
    • Ruby 1.8.7-p72
  • rbtrace
    • rubyプロセスにアタッチして、いろいろ情報を取れる
  • 新しいRubyをCIで試したい
  • REE
    • CIのパフォーマンスを上げる
      • パフォーマンス測定
        • cpu time
          • system
            • strace
          • user
        • idle time
          • disk
          • network
      • forkに時間がかかってた
      • posix-spawn gemに変えることで2倍速く!
  • Ruby 1.9.3-p231
    • まず文法を互換に
    • Date/DateTimeのマーシャリング
    • 1.8と1.9からmemcacheを共有
      • どっちからも読めるように
    • encoding
      • YARVをパッチして1.8みたいに振る舞わせる
      • gitがエンコーディングを持っててくれないのが困る
    • 全部のサーバに入って変えるのは大変
      • シェルスクリプトを作って、切り替え
      • bundlerがshebangをそこに向ける
  • script/bench-app
    • cpu time / idle time
  • rblineprof
    • 行ごとにプロファイリング
  • Ruby-coreにコミット権をもらう
  • Ruby 2.1
    • 新たなAPI
      • Profileing/Tracing
      • GC
    • 本番で少ないオーバヘッドで計測できる
    • バックトレースをたくさんサンプリングしてボトルネックをみつける
    • Ruby 2.1.2-github
      • tcmalloc/jemallocが選べる
  • stackprof
    • stackprof: flamegraphs
    • 見たいところを選んでズームしたり
  • ObjectSpace.dump
    • memory leakを見つけたり
  • Rubyの切り替え
    • vendor/ruby-SHA1にRubyを置くようにした
    • 切り替えが簡単に
  • peek status bar

まとめ

  • Ruby 2.1は本番でつかえるよ
  • profilingとobject space APIは計測を簡単に
  • パフォーマンス改善にはRubyがどう振る舞うか知る必要がある

質問

Rubyでこれからどこよくしたい?

Tracing APIをもっと。特定のクラスや特定のメソッドにスコープして、とか。

ランダムな遅さをどう特定してる?

難しいね。本番でプロファイラを走らせられるようオーバーヘッドを減らしておけば、いつでも測れるようになる。

online vs offline profiling。どれをオンラインで動かしてる?

オンラインで使うために作ってるよ。データ取得のためのサーバを用意してる。

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