$30 off During Our Annual Pro Sale. View Details »

ストリーム処理ライブラリはなぜ必要なのか

 ストリーム処理ライブラリはなぜ必要なのか

@関数型ストリーム処理勉強会 http://connpass.com/event/20174/

Fujimura Daisuke

November 07, 2015
Tweet

More Decks by Fujimura Daisuke

Other Decks in Programming

Transcript

  1. ストリー
    ム処理ライブラリはなぜ必要なのか
    2015/11/07
    藤村大介

    View Slide

  2. 自己紹介

    藤村大介
    ● https://twitter.com/ffu_
    ● https://github.com/fujimura
    ● Haskeller/Rubyist

    View Slide

  3. この発表について
    Haskell
    でストリー
    ム処理ライブラリが必要とされた背景を説明します。
    かつて、
    ストリー
    ムデー
    タを扱う方法としては、Handle
    を使う方法、Lazy IO
    がありました。
    しかし、
    それぞれに問題があり、
    再利用性が高く堅牢なコー
    ドを書くことは困難でした。
    この状況を解決すべく、Conduit、Pipes、io­streams
    などのストリー
    ム処理ライブラリが現れ
    たのですが、
    そもそもそれらが必要とされた経緯は具体的にはどのようなものだったのでしょ
    うか?
    既存の方法(Handle、Lazy IO)
    で起こる問題と、
    それがいかに解決されるかを、
    改め
    てここで確認してみようというのがこの発表の趣旨です。
    この発表は ​
    http://okmij.org/ftp/Haskell/Iteratee/talk­FLOPS.pdf​
    をベー
    スにしています。
    ソー
    スコー
    ドは ​
    https://github.com/fujimura/functional­stream­processing­meetup­sample​

    す。

    View Slide

  4. そもそもストリー
    ムとは?
    必要に応じて処理されるデー
    タの連なりのこと。
    具体的には標準入力、
    ファイル、
    ソケットな
    ど。
    上記の定義はScheme
    の​
    実装提案書​
    より。
    この定義では入力側をストリー
    ムと読んでいます
    が、
    出力側(
    標準出力への書き込みなど)
    もストリー
    ムとして扱われてる場合が多い気がしま
    す。
    ストリー
    ムは多くの場合、​
    I
    O

    です。

    View Slide

  5. 具体例:200mb
    のテキストファイルに含まれる空白文字の数を調べる
    200mb
    のファイルをメモリ上に読み込むのは効率的とは言えません。
    ストリー
    ム処理の出番で
    す。
    まずはLazy IO
    を使う例、Handle
    を使う例を見てみます。
    それぞれのうまくいかない箇所
    を確認して、
    最後にio­streams
    を使う例でそれらが解決される様子を見ることにします。

    View Slide

  6. 1) Lazy IO

    良いところ

    単純でわかりやすい

    悪いところ

    純粋な関数で例外が起こる
    ■ r
    e
    a
    d
    F
    i
    l
    e

    で読んだファイルに不正なバイト列が含まれていた場合は例外が起こり
    ます 。
    そして、Haskell
    は遅延評価なので、
    値は必要になった時に評価され、

    1
    外は評価時に発生します。
    つまり、
    評価されるまで例外は発生しないのです!

    の性質により、
    なんと純粋な関数で例外が起こることがあります。
    これのデバッ
    グは非常に難しいです。

    いつ、
    どれだけファイルが開かれ、
    開放されるか予測しにくい

    上記と同じ理由でファイルが開放されるタイミングも単純には予測できません 。
    2
    大量のファイルが同時に開かれてしまう場合もあります。
    1
    上記のコー
    ドの場合、​
    L
    T
    .
    f
    i
    l
    t
    e
    r

    で不正なバイト列が評価される時に発生します。
    2 ​
    s
    e
    q

    や​
    B
    a
    n
    g
    P
    a
    t
    t
    e
    r
    n
    s

    を使ってサンクを潰して回る羽目になります。

    View Slide

  7. 2) Handle

    良い所

    素朴で理解しやすい

    悪いところ

    ロー
    レベル

    素朴さの裏返しですが、Oleg
    さん言う所の「Haskell
    で書かれた、
    典型的なC

    コー
    ド」
    で、
    実にロー
    レベルです。
    関数プログラミングとは何だったのか!
    3

    ロジックを書いている部分より、Handle
    の世話をしている部分が多い

    実際、
    ロジックが複雑になると大変なことになります。
    コー
    ド量が増えると、

    れだけバグの入る可能性も増えます。
    3 ​
    http://okmij.org/ftp/Haskell/Iteratee/talk­FLOPS.pdf​
    の7
    ペー
    ジ参照

    View Slide

  8. 3) io­streams

    良い所

    ハイレベルでコンポー
    ザブル

    ストリー
    ム自体の扱いはio­streams
    が隠蔽しています。

    ストリー
    ムを受け取る関数を、Unix
    のパイプのように ​
    >
    >
    =

    で処理を繋ぎます。

    がれたそれぞれ処理は抜き差しがしやすいので 、
    部品化も簡単です。
    4

    安全な例外

    それぞれの部品は​
    I
    O (
    I
    n
    p
    u
    t
    S
    t
    r
    e
    a
    m a
    )

    を返すので、​
    b
    r
    a
    c
    k
    e
    t

    で例外を捕捉でき
    ます。

    少ないメモリ使用量
    ■ io­streams
    が面倒見てくれます。

    悪いところ
    ○ \(^o^)/
    ない
    4 io­streams
    で入力を処理する場合、 ​
    I
    n
    p
    u
    t
    S
    t
    r
    e
    a
    m a ‐
    > I
    O (
    I
    n
    p
    u
    t
    S
    t
    r
    e
    a
    m a
    ) ​
    を繋いでいくことになります。

    View Slide

  9. まとめ
    既存の解決方法には問題がある。
    ● Lazy IO:
    純粋な関数で例外が起こる、
    リソー
    ス管理が難しい
    ● Handle:
    関数プログラミングっぽくないロー
    レベルなコー
    ドになる
    ストリー
    ム処理ライブラリで、
    それら問題を解決できる。
    ● io­streams:
    サプライズの少ない例外 、
    ハイレベルでコンポー
    ザブル
    5

    リソー
    ス管理は自分でやらないといけないけど…
    ストリー
    ム処理ライブラリを活用すると、
    効率がよく、
    見通しがよく、
    サプライズが少ないプ
    ログラムが書けるようになります。
    5
    実はこれHandle
    でも​
    w
    i
    t
    h
    F
    i
    l
    e

    を使えば実現できます。

    View Slide

  10. おまけ

    例外処理
    ○ Conduit: ​
    resourcet
    ■ https://www.fpcomplete.com/user/snoyberg/library­documentation/resourcet
    ○ Pipes: ​
    pipes­safe
    ○ io­streams: ​
    bracket​
    を使ってくれとのこと

    View Slide

  11. 参考資料&
    リンク集
    ● io­streams
    ○ https://hackage.haskell.org/package/io­streams
    ● Conduit
    ○ https://hackage.haskell.org/package/conduit
    ● Pipes
    ○ https://hackage.haskell.org/package/pipes

    サンプルコー

    ○ https://github.com/fujimura/functional­stream­processing­meetup­sample

    ストリー
    ム処理ライブラリブー
    ムの端緒となったIteratee
    論文
    ○ http://okmij.org/ftp/Haskell/Iteratee/describe.pdf
    ● Iteratee
    についての発表資料。
    わかりやすい
    ○ http://okmij.org/ftp/Haskell/Iteratee/talk­FLOPS.pdf
    ● Iteratee
    の紹介
    ○ https://themonadreader.files.wordpress.com/2010/05/issue16.pdf

    和訳: ​
    http://d.hatena.ne.jp/tanakh/20100824
    ● io­streams
    リリー
    スのお知らせ&
    紹介。Conduit, Pipes
    との比較もある
    ○ http://snapframework.com/blog/2013/03/05/announcing­io­streams
    ○ Reddit
    のスレッドが盛り上がった。
    面白いです
    https://www.reddit.com/r/haskell/comments/19qfr6/announcing_first_release_of_iostreams/
    ● Conduit, Pipes, io­streams
    の比較 by Conduit
    の作者Simon
    さん
    ○ https://www.reddit.com/r/haskell/comments/18iskd/upcoming_conduit_10_comparison_to_pipes_iostreams/
    ● Lazy IO
    の罠
    ○ http://newartisans.com/2013/05/three­examples­of­problems­with­lazy­io/
    ● Conduit
    概要
    ○ https://www.fpcomplete.com/user/snoyberg/library­documentation/conduit­overview

    View Slide