若いプログラマが問題を解くと

1,282 views
1,175 views

Published on

Code HAIKU 2012の発表資料です。
http://atnd.org/events/33788

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,282
On SlideShare
0
From Embeds
0
Number of Embeds
267
Actions
Shares
0
Downloads
1
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • Map('x -> "Desknet's NEO", 'x -> "Cybozu Office 9"). get('x). map( _ + " is the great").getOrElse("What is"). union(" collaboration software")
  • 若いプログラマが問題を解くと

    1. 1. 若いプログラマが問題を解く と 村崎 大輔 daisuke-murasaki@cybozu.co.jp 2012-12-16
    2. 2. Outline• 自己紹介• 今日の一句• とある製品の検索機能について
    3. 3. 自己紹介• 村崎 大輔 (むらさき だいすけ)• サイボウズ株式会社 松山開発部• メールワイズなどの開発をしています
    4. 4. 今日の一句
    5. 5. 問題1• サイボウズ Office と、サイボウズ ガルー ン どちらが素晴らしいグループウェアか
    6. 6. Scalaで聞いてみよう
    7. 7. 問題を記述するMap(x -> "Cybozu Garoon", x -> "Cybozu Office 9"). get(x). map( _ + " is the great"). getOrElse("What is"). union(" collaboration software")
    8. 8. 回答
    9. 9. 先の問題のポイント サイボウズ Office 9 はすばらしいグループウェア ではなく、
    10. 10. プログラミング言語やライブラリの設 計が 書かれるコードのセンスを左右する
    11. 11. 問題2• 対応表にキーと値が入っている(文字 列) – 対応表:マップ、ハッシュ表、連想配列• 何かキーが与えられたとき、 – 対応表に値が入っていればその値 – 値が見つからなければ "not found" を表示したい
    12. 12. C + GLibの場合value = g_hash_table_lookup(table, key);if (value) { puts(value);} else { puts("not found");}
    13. 13. そうだ!?演算子を使おうvalue = g_hash_table_lookup(table, key);puts(value ? value : "not found");
    14. 14. 他のプログラミング言語だと どうなるか?
    15. 15. Rubyの場合value = table[key]if value puts(value)else puts("not found")end
    16. 16. ||演算子を使うvalue = table[key]puts(value || "not found")
    17. 17. A || B• C言語の場合 – Aを評価して真であれば 1 – そうでなければ、Bを評価して 真であれば 1、偽であれば 0• Rubyの場合 – Aを評価して真であれば A – そうでなければ、Bを評価して B
    18. 18. 実は、 Hash#fetch を使うとvalue = table.fetch(key, "not found")puts(value)
    19. 19. ここからが本題
    20. 20. 問題3• キーを与えて、 – 対応表に値(文字列)が入っていれば "found 値" – 値が見つからなければ "not found" を表示したい
    21. 21. C with GLib の場合value = g_hash_table_lookup(table, key);if (value) { printf("found %sn", value);} else { puts("not found");}
    22. 22. スッキリ書けない
    23. 23. Rubyだと?value = table[key]if value puts("found #{value}")else puts("not found")end
    24. 24. 式展開• 文字列式の中に、別の式を評価した結果 の値(を文字列にしたもの)を埋め込む – "1+2 = #{1+2}" → "1+2 = 3"• テンプレートエンジンでは無くては困る 機能 – サイボウズOfficeなどのかんたん系でも 使ってます(厳密には式じゃない)
    25. 25. Scalaだと?val value = table.get(key)if (value.isDefined) { println("found " + value.get)} else { println("not found")}
    26. 26. ちょっとめんどくさい?
    27. 27. value = table[key]if value puts("found #{value}")else puts("not found")endval value = table.get(key)if (value.isDefined) { println("found " + value.get)} else { println("not found")}
    28. 28. ScalaのMap• get(key) で返ってくる値は、値そのもので は なくOption型に値が入ったもの• 中に値が入っているかを調べるには value.isDefined• 中に入っている値を返すには value.get
    29. 29. まだまだ!Optionはこんなものじゃな い!
    30. 30. Option#map(f)• Optionが空でなければ、値を関数 f に与えて 評価して、その値を返す value.map("found " + _)• JavaScriptで書くとすれば value.map(function(v) { return "found " + v });
    31. 31. 使ってみましょうval value = table.get(key)val mapped = value.map("found " + _)if (mapped.isDefined) { println(mapped.get)} else { println("not found")}
    32. 32. Option#getOrElse(v)• Optionが空でなければ、その値を返す• Optionが空であれば、v を返す
    33. 33. 使ってみましょうval value = table.get(key)val message = value.map("found " + _)println(message.getOrElse("not found"))
    34. 34. まとめちゃいましょうprintln( table.get(key). map("found " + _). getOrElse("not found"))
    35. 35. せんせい!Perl Rubyでもできますか?!
    36. 36. できないことはないvalue = [table[key]].compactmessage = value.map {|v| “found #{v}”}puts(message.first || "not found")
    37. 37. ちょっと無理がある
    38. 38. それって○○でも(ry
    39. 39. それって○○でも(ry• Haskell – Maybe• C++ – Boost.Optional など• C# (.NET) – Nullable• SQL – NULL
    40. 40. ここまでのまとめ• 同じことをするために必要なコードは、 プログラミング言語によってまちまち• 同じプログラミング言語でも、 使い手の知識と思考によってコードが変 わる• どんなコードが美しいかは人それぞれ
    41. 41. 最初のCodeを もう一度
    42. 42. サイボウズOfficeはすばらしい (ryMap(x -> “Cybozu Garoon", x -> "Cybozu Office 9"). get(x). map( _ + " is the great"). getOrElse("What is"). union(" collaboration software")
    43. 43. とある製品の検索機能
    44. 44. とある製品
    45. 45. 遅い…
    46. 46. なぜメールワイズの検索は遅いの か• 対象のメール「全て」をデータベースか ら読み 込み、条件判定する• 対象のメールが多くなると、データベー スから読み込む時間がネックになる
    47. 47. 読み込み≒コピーの繰り返し• ディスクからOSにデータをコピー• OSからDB (SQLite) のバッファにコピー• 呼び出し元が確保したバッファにコピー• バッファの中身 (BLOB) をデシリアライズして 読み込まれたオブジェクトが復元される(コ ピー)
    48. 48. コピーを減らそう• いったん読み込んだオブジェクトを、次 に必要になったときに使い回す – 一つのプロセス単位ではやっている• これをプロセスを越えて共有する• コピーが減る
    49. 49. Boost.Interprocess• プロセス間の通信などを提供するライブラリ• Memory-mapped files – ファイルの中身をプロセスのメモリ空間にマップ する – ファイルが同じであれば、別のプロセスでも同じ メモリ内容が見える• Relative pointers – マップされたファイルの場所を指すポインタ – マップされる場所はプロセスごとに違うが、そこ をうまく変換してくれる
    50. 50. Boost.Interprocess• マップされたメモリの上に、STL風なコン テナを作ることができる• 後でリクエストを処理するときも、マッ プした コンテナには前の内容が残っている
    51. 51. とりあえずやってみた• インターンに来ていた郭さんにやってみ てもらいました(右から2番目)
    52. 52. とりあえずやってみた• デシリアライズ前のBLOBを、メモリマッ プされたmapコンテナに入れる – コンテナにあれば、コピー不要でデシリアラ イズできる• サイボウズOfficeのカスタムアプリを対象 に、検索時間を計測 – 10~20%の性能向上
    53. 53. おお、メール検索も 速くなりそう?
    54. 54. ちょっとまった!
    55. 55. ひょっとして• メールの全てを読み込む必要はない?• メールに現れる単語を全て抜き出して、 単語 → メールの対応表を作っておけばいいのでは?
    56. 56. 転置インデックス (inverted index)• 全文検索システムで使われるデータ構造• レコード単位転置インデックス (record level) – (単語)→(単語を含む文章)すべてのリス ト• 単語単位転置インデックス (word level) – (単語)→(単語を含む文章, 出現位置)のリ スト
    57. 57. 全文検索システム• Namazu• Apache Solr• Senna• Hyper Estraier
    58. 58. 後半のまとめ• プログラムが遅い原因はいくつもある が、 無駄なコピーをしていることがよくある• 効率を求めるなら、無駄なコピーを減ら しましょう• それよりも、データ構造とアルゴリズム が大事
    59. 59. まとめ• よいプログラミング言語• よいデータ構造• よいアルゴリズム• よいライブラリ
    60. 60. ご清聴ありがとうございまし た

    ×