haya14busa

haya14busa’s memo

Golangにおけるinterfaceをつかったテストで Mock を書く技法

いい記事に感化されて僕も何か書きたくなった。

Golangにおけるinterfaceをつかったテスト技法 | SOTA

リスペクト:

今週のやつではなく先週のです.今週のは特に知見がなかった…grpc-goとか使えたらクライアント勝手に生成されるしいいよねgrpc流行ると便利そう(感想) くらい

Golangにおけるinterfaceをつかったテスト技法 | SOTA めっちゃいいなーと思ったんですが,テスト用 の mock を気軽に作るテクニックはあまり詳しく紹介されてなかったのでそのあたりの1つのテクニックを書きたい.

前提

僕もテストフレームワークや外部ツールは全く使わない.標準のtestingパッケージのみを使う. testify もいらないし, mock するために gomock も基本はいらない.

とにかくGolangだけで書くのが気持ちがいい,に尽きる.

テスト用 fake client をつくる

全体の動くはずのgist: https://gist.github.com/haya14busa/27a12284ad74477a6fd6ed66d0d153ee

例えばこういう実装のテストを書くときのことを考えます.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package main

import (
  "context"
  "fmt"
)

type GitHub interface {
  CreateRelease(ctx context.Context, opt *Option) (string, error)
  GetRelease(ctx context.Context, tag string) (string, error)
  DeleteRelease(ctx context.Context, releaseID int) error
}

type GhRelease struct {
  c GitHub
}

func (ghr *GhRelease) CreateNewRelease(ctx context.Context) (*Release, error) {
  tag, err := ghr.c.CreateRelease(ctx, nil)
  if err != nil {
      return nil, fmt.Errorf("failed to create release: %v", err)
  }

  // check created release
  if _, err := ghr.c.GetRelease(ctx, tag); err != nil {
      return nil, fmt.Errorf("failed to get created release: %v", err)
  }

  // ...
  return &Release{}, nil
}

type Option struct{}
type Release struct{}

GitHub interface をテストでは mock したものを使いたい.そういうときには以下のように mock を作ると便利です.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type fakeGitHub struct {
  // インターフェース埋め込み
  GitHub
  FakeCreateRelease func(ctx context.Context, opt *Option) (string, error)
  FakeGetRelease    func(ctx context.Context, tag string) (string, error)
  // 埋め込みを使うので,例えば DeleteRelease はまだテストしないので mock
  // しない... いうことができる.
}

func (c *fakeGitHub) CreateRelease(ctx context.Context, opt *Option) (string, error) {
  return c.FakeCreateRelease(ctx, opt)
}

func (c *fakeGitHub) GetRelease(ctx context.Context, tag string) (string, error) {
  return c.FakeGetRelease(ctx, tag)
}

fakeGitHub という struct を作成し,インターフェースをとにかく満たすために GitHub interface を埋め込みます.

そして mock したいメソッドは新たに func (c *fakeGitHub) CreateRelease(...) (...) と 定義しなおし,実装の中身は fakeGitHub に持たせた FakeCreateRelease field に丸投げします.

このようにしてテスト用 mock を作るとそれぞれのテストで簡単に中身の実装を変えられるので大変便利です.

実際にテストしてみる例

main_test.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package main

import (
  "context"
  "fmt"
  "testing"
)

type fakeGitHub struct {
  // インターフェース埋め込み
  GitHub
  FakeCreateRelease func(ctx context.Context, opt *Option) (string, error)
  FakeGetRelease    func(ctx context.Context, tag string) (string, error)
  // 埋め込みを使うので,例えば DeleteRelease はまだテストしないので mock
  // しない... いうことができる.
}

func (c *fakeGitHub) CreateRelease(ctx context.Context, opt *Option) (string, error) {
  return c.FakeCreateRelease(ctx, opt)
}

func (c *fakeGitHub) GetRelease(ctx context.Context, tag string) (string, error) {
  return c.FakeGetRelease(ctx, tag)
}

func TestGhRelease_CreateNewRelease(t *testing.T) {
  fakeclient := &fakeGitHub{
      FakeCreateRelease: func(ctx context.Context, opt *Option) (string, error) {
          return "v1.0", nil
      },
      FakeGetRelease: func(ctx context.Context, tag string) (string, error) {
          return "", fmt.Errorf("failed to get %v release!", tag)
      },
  }

  ghr := &GhRelease{c: fakeclient}

  release, err := ghr.CreateNewRelease(context.Background())
  if err != nil {
      t.Error(err)
      // => failed to get created release: failed to get v1.0 release!
  }
  _ = release
  // ...
}

以下のような感じで,簡単にテスト用mockの実装を書いて,テストすることができます.

1
2
3
4
5
6
7
8
fakeclient := &fakeGitHub{
  FakeCreateRelease: func(ctx context.Context, opt *Option) (string, error) {
      return "v1.0", nil
  },
  FakeGetRelease: func(ctx context.Context, tag string) (string, error) {
      return "", fmt.Errorf("failed to get %v release!", tag)
  },
}

上記の例では1種類の実装しかテストしてないのであまり恩恵がわかりづらいかも知れないですが, 例えば error が帰ってきたときに正しくエラーハンドリングできてるかとか, 返り値をいろいろ変えたものをいくつか作ってテストする…といったことが上記のパターンを 使うことによって簡単にできます.Table Testing することも可能.

普通にわざわざstructごと作っていると,例えばテストの関数ないでは struct の method (e.g. func (c *client) Func()) を定義することができません.

そこで FakeFunc func() というfield を持たせて実装を丸投げすることによって, 簡単にいろんな実装のテスト用 mock を作成してテストができるということの紹介でした.

まとめ

僕は最初にこのパターンを教わってなるほどなぁ…と思ったんですが,いざ世にでてみると(?) ぜんぜんこのパターンを紹介しているものが見つからなかったので紹介してみました. (一応どっかの medium の英語記事にこれに似たパターンが紹介されてたのを見た気もする…)

ぜひ使ってみてください.

あまり関係ない追記

この記事の主旨とは関係ないけど,基本的にテスト用ライブラリは使わないとはいえ, たまににヘルパー関数ほしいなーというケースがあります.

でかい struct をテストで比較するときに,比較自体は reflect.DeepEqual で出来るのだけど, もし違っていたときにどこが違うかを表示するのが面倒くさいのでヘルパー関数提供してくれるライブラリがほしい…

某社でgoのテスト書いてたときもこういう大きめのstruct比較するケースでは便利diff表示用ライブラリを 使っていた気がしたんだけど,なんかOSSで見つからない気がする… prettycmp みたいな名前だった気がするが どうだったか… そもそも記憶違いな気もする…

追記: twitter で教えてもらいましたが https://github.com/kylelemons/godebug っぽいです. 便利. https://godoc.org/github.com/kylelemons/godebug/pretty#Compare

Reviewdog を飼ってコードレビューや開発を改善しませんか

reviewdog logo

GitHub: haya14busa/reviewdog: A code review dog who keeps your codebase healthy

英語記事: reviewdog — A code review dog who keeps your codebase healthy – Medium

reviewdog というlinter などのチェックツールの結果を自動で GitHub の Pull Request にコメントしたり, ローカルでも diff の結果から新たに導入されたエラーだけを表示するようにフィルタリングできるツールを作りました.

英語記事 を Medium に書いたし,README も書いたので 日本語記事はまぁいらないかなぁと思ったけど,柄にもなく Vim 関連以外で普通に便利ツールを書いてしまって,これは日本語でも簡単に共有しようかなぁと思いこの記事を書いています. (とはいえ機能の実現方法として Vim は関係はしてるんですけどね.)

特に和訳とかではなく,英語ではなかなか文章に落としづらかったことをだらだら書こうかと思います.英語は難しい… (だらだらと日本語を書いてるので日本語ができてるとは言ってない)

背景とかきっかけ

compiler や lint といったコードをチェックするツールはものによっては直さなくてもいいものをレポートすることがありますよね. 例えば Scala の compiler はオプションを与えたらかなりいろんな警告を出してくれますが, 別に直さなくてもいいケースがあるものがあったり, Play framework で使ってると ルーティングファイルやテンプレートファイルに対して,こちらが直せない警告を バンバンだしてきたりします.(これはバージョンを上げると直るっぽい?)

golint-set_exit_status を付けないと問題を見つけても exit status が 1 になりませんが, これはもともとあくまで コーディングスタイル の問題を見つけるものだという思想からでしょう.

Golint differs from govet. Govet is concerned with correctness, whereas golint is concerned with coding style.

Go の OSS プロジェクトでは CI で golint の問題があればビルドをFAILにすることが結構多いと思いますが, 本来直さなくてもいいところまで直さなくてはいけなくて消耗したりしていませんか?

去年 Google のインターンで Go 書いてたときは,実際 golint のエラーでテストがfail するとかではなく, bot が自動でコメントしてくれてあとは勝手に直せという感じで便利でした.

まぁ直さなくてもいい結果は少なくて大抵は直すのですが,直さなくてもいいものはゼロではないです. コメントで bot に直さなくてもいいものを指摘されたら単に無視してcloseすればいいので無駄に消耗せずにすんで便利.

また CI で落とすために指摘してくれると便利なことは多いけど設定で off にしてしまうケースもあるかなーと思います. 例えば JavaScript で関数の引数に使ってないものがあったら警告してくれると便利なケースもあるかなぁーという反面, コールバック用関数などでは渡ってくるのがわかってるからいいんだよ!というケースとか.

あとは既存のコードベースに新しく linter を導入しようとすると,既存のコードに対してエラー 出まくって導入するために直していくのが面倒だなぁ… 放置していると新しいコードに対しても lint が走らないので消耗する…ということもあるかと思います.

上記の問題を解決する1つの方法としては,とりあえずPull Request の差分に関して lint をかけたり して自動でbotがコメントしてくれる仕組みがあれば,100% 円満解決ではなくともかなりつらみが 解消されるかと思います.

世の中にはすでにそういうサービスは一応あって Hound CI とか SideCI がそうなんですが,使える言語やツールは限られています. たとえば Vim の linter を Vim プラグインのレポジトリに対して使えるようになることはないでしょう.

また,ローカルでも(差分に対して lint などを書けるという意味で)実行できないと Pull Request 出さないとチェックできないので不便です.

ということで作ったのが reviewdog になります.

あんまり技術的に面白いことがあったというよりは,本来あるべきものなのになかったので作ったという感じ. 汎用的に lint の結果をパースする手段をどのツールも提供してるものがないのが問題で, reviewdog は Vim の Quickfix 用の ‘errorformat’ という機能を Go で port することによって実現しました.

GitHub: haya14busa/errorformat: Vim’s quickfix errorformat implementation in Go

‘errorformat’ 形式を採用したのは僕が単に Vimmer だから… というのももちろんあるんですが, 仕様の全体を理解するのは結構大変とはいえ,簡単なerrorformatを書くのは簡単だし,それでいて 難しい複数行のエラーメッセージをパースできる利点があります.

emacs では compilation モードが Vim の quickfix に対応するようで,errorformat に対応するものは 正規表現とサブマッチのインデックスっぽいのですが,簡単な複数行エラーには対応してそうですが, Vim の ‘errorformat’ のほうが汎用的っぽいなーと思いました(詳しく見れてません)

‘errorformat’, 実装ポーティングして仕様を理解していくと,かなりよくできているなーという印象で Vim は時代の先を走ってると思いました.

また reviewdog 以外でも https://github.com/alecthomas/gometalinter のもっと汎用的なバージョンを言語を問わず errorformat を使って作るとかも可能なんじゃないかな〜と思います.(gometalinter 個人的にあんまり好きくないし)

インストールとか使い方書こうかと思ったけど疲れたのでREADMEとか英語のpost読んでください

あと雑だけど Google Doc の design doc な何かも一応ある reviewdog - Google Docs

CI サービス連携問題

reviewdog は Pull Request hook と実行環境さえあれば対応できてオープンなCIサービスの場合はGitHubへコメントするための API トークンを安全に環境変数などで保存する方法があれば対応できます.

travis や circle ci といったメジャーなCIサービスは両方対応していて,最初は全然このあたりは問題ではないなーと思ってたのですが, 実はOSS用のリポジトリに対して使おうとすると fork レポジトリからの pull-request では暗号化された環境変数は使えない! という問題があって,これどうすかなぁーということにかなり悩まされました. 考えてみれば当たり前で,echo $SECRET_VAR とかした悪意あるPull Request が開かれたら簡単に漏れちゃいます.

そこで,いろいろ CI サービスを探ってると https://drone.io/ の OSS バージョン https://github.com/drone/drone を見つけました.

help (Secrets · Drone) を読むと, yaml ファイルのチェックサムとセクション分けによって(完璧ではないものの)安全に 秘密の環境変数をforkからのプルリクでも使えるようになっているようです. 完全に便利なので travis とか circle ci でもこの機能ほしい…

drone.io OSS バージョンは https://drone.io/ とは別物という感じで環境変数の扱い以外も 結構便利っぽく,drone.io も reviewdog はデフォルトでサポートしました.

ただ OSS で雑にGitHubに上げたサービスに対して使うケースでも drone.io をどこかにホスティングしなくてはならないのが不便なところです… 個人的にはreviewdogのために Degital Ocean に月500円で drone.io 用サーバを立ててみて, 今の所かなり便利感ありますが,ワガママをOSS用にどっかホスティングしてほしい.

で,じゃあ結局forkからのPull Requestも受け付けるOSS用リポジトリにreviewdog導入 したい場合どうすればいいかというと,現状は Circle CI の Building Pull Requests from forks - CircleCI 機能をセキュリティリスクと引き換えに ON にするしかないかなーという感じです.

GitHub の Personal Access Token, しかも scope を適切に public_repo とかに設定しておけば, もし漏れても大したことはできないはずだし,rebokeもできるし,fork して悪意あるPull Request 作られたら流石に気付くし, まぁそもそもそんなこと GitHub の 権限すくないPersonal Access Token 得るためにやる人は 少ないのでは… という感じですね.ただ使う場合はもちろん自己責任でお願いします.

Circle CI か travis あたりが drone.io みたいに yaml のチェックサム+環境変数が使えるスコープを制限する機能がもし実装されたらそれを使っていきたい

(ところで他のCIサービスとして wrecker 試したんですが,fork からの pull-request で普通に秘密の環境変数使えてしまった気がする…問題では…あとPull Request hook によるビルドがなさそうだった)

終わりに

reviewdog 完全に便利という感じなのでぜひ使ってみてください〜

CI 用環境変数とか設定すれば Jenkins とかいろんな環境で導入できるはずだし, 一度導入したら撤退しずらいとかもないので,ギョームとかでも使えるような気がしますが リリース直後なのでいろいろ変わるかも知れないしそのへんはよしなにお願いします. GitHub Enterprise とか BitBucket 対応は気が向いたらするかもしれない. 特にGitHub Enterprise はGitHub 用の base の url 変えるだけで対応できる…?

ちょくちょく気になるところはあるのでちまちま改善していこうかなーと思います

はてな・ペパボ技術大会〜インフラ技術基盤〜@京都 行ってきたメモ

はてな・ペパボ技術大会〜インフラ技術基盤〜@京都 7/2

はてな・ペパボ技術大会〜インフラ技術基盤〜@京都 - connpass

行ってきました.メモってたのでせっかくなので共有しておきます. gistでいいかとおもったけどスライド埋め込みとか考えたらブログに雑に投げたほうが見なおしやすそうと思ったのでブログで. 自分で発表したわけでもないし,感想とか書いてるわけでもないけどまぁいいかってカンジ.

注意

わかってない人が書いたメモなのでいろいろわかってないメモが書かれてます. 理解度に関係なく聞き漏らしたところ雑に書いたりしてるので発表様がおっしゃってた話とちがうところもあるかもしれない. 特に座談会の内容とかは Twitterのハッシュタグみてたら @matsumotory さんと @yumu19 さんがまとめてたのでそっち見たほうがわかりやすいかも.

Togetter

http://togetter.com/li/994969

ということで雑にtogetterつくっておきました.#pepabohatena で検索したやつからスパム2-3個消しただけです. そういえばtogetterだめな人とかいるかもじゃん…!ということに気づいたんですが全員に連絡するの流石につらいのでダメなひと @haya14busa まで連絡していただければ幸いです.勝手に使って申し訳ないでした :bow:

記事書いてる間に @yumu19 さんが作ってた -> はてな・ペパボ技術大会〜インフラ技術基盤〜@京都 #pepabohatena ツイートまとめ - Togetterまとめ

タイムテーブル

time 名前 タイトル 時間
13:30 受付開始・開場 30分
14:00 y_uuki(はてな) 開会宣言・会場説明 5分
14:05 y_uuki(はてな) はてなにおけるLinuxネットワークスタックの性能改善 25分
14:30 matsumotory(ペパボ) Webサービス基盤の自律制御と動的平衡性 25分
14:55 休憩 5分
15:00 ichirin2501(はてな) 計算量と僕とWeb開発 25分
15:25 pyama(ペパボ) STNS 〜点と線を結び新しい何かを作るコト〜 25分
15:50 休憩 5分
15:55 masayoshi(はてな) 負荷分散技術を選ぶ時に考えること 25分
16:20 monochromegane(ペパボ) サービスに寄り添うログ基盤 - ログ収集のその先に - 25分
16:45 休憩 10分
16:55 masayoshi(はてな) taketo957(はてな) alotofwe(ペパボ) hanazuki(ペパボ) モデレータ stanaka(はてな) 若手インフラ座談会 40分
17:35 懇親会 軽食と飲み物を用意しています!
19:00 お開き

開会宣言・会場説明

14:00 | y_uuki(はてな) | 開会宣言・会場説明 | 5分

  • 発表6本+座談会
  • アンケート

はてなにおけるLinuxネットワークスタックの性能改善

14:05 | y_uuki(はてな) | はてなにおけるLinuxネットワークスタックの性能改善 | 25分

はてなにおけるLinuxネットワークスタックパフォーマンス改善 / Linux network performance improvement at hatena // Speaker Deck

  • はてなのウェブオペレーションエンジニア.新卒1年目の仕事
  • 今は3年目
  • 3層構成 LB <-> proxy <-> application <-> database
  • ボトルネックどこ?
    • CPU: %user/%sys/%iowait
    • Mem: used/cached/buffer
    • Disk: read/write
    • NW: tx/rx/tx
  • ソフト割り込み(パケット受信)の負荷が高いときの話 (%soft)
  • ネットワークスタック
    • ネットワークi/oを実現するために必要な要素群.低レイヤより
      • NIC/パケット送受信/etc…
  • ネットワークI/O 高速化
  • パケット受信フロー NIC -> Kernel -> Process
    • この辺の話かな? 8.3. パケット受信の概要
    • NIC: 物理デバイス
    • ネットワークカード - Wikipedia
    • NIC ->(ハード割り込み) -> パケット受信 -> プロトコル処理 -> データ受信処理 -> Process
    • 割り込み2種類ある.なぜか?
    • ハード割り込みだけだとパケット受信のたびにプロトコル処理まで実行しちゃう
    • なので一旦バッファにいれる.ソフト割り込み
  • NAPI (New API)
    • 1パケットずつでなく複数パケットごとに割り込み
    • ポーリングによってとってくる.待ち時間発生するので負荷が高い時だけやるみたいに賢くなってる
    • ソフト割り込みを減らす
  • HAProxy の台数増問題 (実際に取り組んだやつ)
  • 割り込みが多い -> 割り込み減らしたい
  • HAProxy のネットワーク負荷が高いのでHAProxyを DNS RR で並べた
  • Interrupt Coalescing
    • ハード割り込みを減らす
  • NICドライバのパラメータ検証した
  • RPS (Receive Packet Steering)
    • コア間割り込み
  • RPS でRedisチューニング
    • Redisは1スレッド
    • カーネルのネットワークI/O処理するスレッドと Redisのスレッドは分散可能
    • -> CPU% 10% 減 (コンテキストスイッチが減ったり,キャッシュが効くようになったからっぽい)
    • redisの公式ページにやりかた書いてある http://redis.io/topics/benchmarks
  • ユーザランドへゼロコピー
    • そもそもカーネルに処理しないという変態処理.
    • パケットを NIC -> ユーザランドへバイパス
    • 実装: netmap
    • まだ実用ではなさそうだけど研究されてる
    • ソケットAPIの限界
      • ソケットAPIではゼロコピーできない
  • まとめ
    • OSの内部面白い.OS内部の技術の外出し
    • ソフト割り込みにより遅延処理
    • ジョブキューのような非同期処理
    • 割り込みとポーリング
    • OSの技術をもうちょっと上のレイヤの技術に応用してやったりするのベンリ

Webサービス基盤の自律制御と動的平衡性

14:30 | matsumotory(ペパボ) | Webサービス基盤の自律制御と動的平衡性 | 25分

  • @matsumotory 松本亮介の研究・開発業績ページ by matsumoto-r
  • 技術基盤チームで研究開発してる
  • 目次
    • なめらかなシステム
    • Webサービスの現状・課題
    • 自立制御
    • 動的平衡性
  • なめらかなシステム
    • システムにとってのユーザ,システムを構成するサーバ等の要素のカテゴリや特徴を詳細に認識する
    • 人間の労苦は避けたい
  • Webサービスの現状・課題
    • bad UI / 遅い / etc… -> 快適に利用できるのが当たり前
    • サーバの運用大変
      • 高負荷・障害対応
      • 問い合わせ
      • バジョンアップ
      • 監視
      • 新規構築
  • 監視に注目してみる
    • 閾値設定はムズカシイ
    • 1時的な高負荷は無視したい.すぐもどるならok
    • 傾向が変わるならすぐ知りたい
    • 正常にみえるけど異常っぽいものを検知したい
    • 段階的な傾向の変化を検知したい.階段みたいな.でも1時的なものは無視
  • 詳細な変化と原因を知るには人の目が必要.でも自動で制御したい
    • 人は何をみてるか? 対象の振る舞いをみてる
    • 振る舞いを表す特徴が知りたい!
    • 人工知能でやれるか
  • 考え方
    • 特徴がある
    • 通常の状態を学習
    • 外れた状態を解析
    • 連速的に外れた状態が異常のはじまり
  • 各種基盤技術
    • [x] 設定をプログラム化
    • [x] リソース制御連携
    • [ ] 特徴量定義と解析 <- ここ
  • 特徴量解析
  • Webサーバの自律制御
    • 特徴量抽出による検知できる点の増加
    • 閾値以下でも傾向変化の細かい検知ができる
  • 細かい傾向変化した時点でどうするか?
    • 異常検知.誤検知もある.false positive/negative?
    • すぐ制限とかは影響でかい
    • なんかアクションはとりたい
    • システムとしてバランスを取りたい条件ある
      • マルチテナント環境とする.
      • リソースが逼迫してきたのみ制限かけたい.自動で制限したい.
      • グラフなめらかにしたい.
    • e.g.
      • どのホストが変化点スコアが高い?
      • 重み付け (優先順位つける) example.com:95, matsumoto-r.jp:93, …
      • 傾向変化ごとに重みつけリスト更新
      • 全リソースが逼迫 -> リストを元に自動制御
      • 逼迫してないなら重みつけリストをつくるところだけしとく
    • 時系列データの生成
      • 相関関係の時系列データも作れる
      • 全体の負荷とホストの負荷どっちか
  • 要素技術
    • 機能拡張 mod_mruby
    • mruby-resource
    • mruby-changefineder
    • etc…
  • 制限の実装方法
    • リクエスト単位でCPU/IOなどの割当を変更
    • cgroup/rlimit
    • e.g. 特定のcgroupにリクエストをアタッチしてCPUを20%に制限する.レスポンス返したらデタッチ
  • ミドルウェアが特徴量抽出解析・制限行いたい
  • webサービスの動的平衡性
    • 生命とは? 動的平衡にある流れ
    • 動的平衡(どうてきへいこう、英語:dynamic equilibrium)とは、物理学・化学などにおいて、互いに逆向きの過程が同じ速度で進行することにより、系全体としては時間変化せず平衡に達している状態を言う。 – 動的平衡 - Wikipedia

    • 細胞周期チェックポイント - Wikipedia
  • 今後: STNS/haconiwa, …
  • Q&A:
    • フォールトトレランスとの違い?
      • 現時点はそこまで.循環するパターン.状態を持つサーバと持たないサーバがある.この辺とかの落とし所を考えてる
    • from yuuki: Docckerとかで動的にスケールしてるけど,違うアプローチっぽい.どう違う? キューバネティスとか?
      • こちらはサーバを積極的に,自主的に落として循環していくといった部分が違う.元気なサーバでも任意の時間経過で落としたり.
    • from astj: バースト.イベントやyahoo砲とかのバズり,が怖い.これを異常検知するのはむずくてなかなか考えても答えが出ない.自律制御のスピード超えてバースト来たらどうする?
      • 全体的にはバーストに対応したい.落とす条件.3時間で落ちそうなやつが1.5時間で落ちたなら1つではく2つのVMを再構築するといった方法あるかも.落としたときに条件によって10倍再構築するとか.

netflix とかも似たようなことやってる感じらしい?

mackerel で出来たりしたら最高だな〜と思った.

計算量と僕とWeb開発

15:00 | ichirin2501(はてな) | 計算量と僕とWeb開発 | 25分

  • @ichirin2501 いちりんちゃんさん
    • アプリケーションエンジニア2年 ->(転職) web オペレーションエンジニア1年(hatena)
    • スピリチュアルな発表!
  • もくじ
    • 計算量について
    • mysql クエリ改善
  • 計算量とは?
    • 大変さの指標.
    • 係数無視 O(3n3) -> O(n3)
    • でかいやつだけ O(n3 + n2) -> O(n3)
  • 計算量といちりんちゃん
    • 競プロで向き合う.
    • 計算量と時間の基準・感覚がある
    • O(107) ~ O(109) 0 -> 1s くらいじゃん?みたいな感じ
    • データサイズからの見積もり
      • 1sec デッドラインの見積もりならこんな感じやろ的な.
      • n <= 106 -> O(n)
      • n <= 105 -> O(nlogn)
      • n <= 3000 -> O(n2)
      • n <= 100 -> O(n3)
      • n <= 20 -> O(2n)
  • MySQL 改善のはなし
    • group by / distinct の迷い.どっちでも重複除外できるので実現可.
      • follow/followerテーブル的なものを想定
      • friend_id 重複なしで 1000件ほしい
      • 結果を言うと group by だと遅いケースがあった
      • group_by で OR句のuser_idが多いと異常におそくなった
      • どう計算してるか知ればいいじゃん
    • インデックス構造
      • インデックス B+tree
      • 主キーのインデックス clustered index
      • 主キー以外のインデックス secondary index (主キーがこれでわかる)
      • B+tree はleafが連結リスト.rangeで検索とかのときにベンリ
      • 例とか.この辺発表の図をみるとわかりやすくてベンリ
    • 話をもどしてfriend_id. なぜ遅いのか?
      • オーダーが違うかも
      • 意図してないインデックスで検索してるかも -> オーダー線形なってるかも
    • 結論そうだった
      • explainするとわかる
      • オプティマイザが間違った判断してた(あるある.経験則). distinct だと解決した
      • 経験則やexplain使わなくても計算量と時間の感覚でどこがまずそうかわかることもあるよ!
        • ミドルウェアのどのへんが悪いかとか計算量の感覚やインデックスの使われ方を理解して推測したり出来るとベンリ
  • Redis の話
    • redis とか
      • kvs nosql(ほかにもグラフデータベースとかあるよねー)
      • list/set/sorted sets(rankingの実装らくとか)/etc .. データ構造いっぱいあってベンリ
      • メモリ最適化 2.2 から入ってる.勝手に圧縮してもらえる
        • -> パラメータ眺めてオーダーとか変わったりするのでは?と推測
    • 怪しいのでパラメータ変えて実際試す
      • データ数と実行時間からオーダーわかる
      • データ数10kで1 sec超えるのオカシイのではと気づく.
    • やっぱり -> データ構造違ってた
      • ドキュメントに実は書かれてたりも.
  • まとめ
    • 知識だけじゃなく感覚を身に着けてるとすぐわかったりしてベンリ.現場で検証しまくるとかできなかたったりするし.
    • まつもとりーさんも言ってたが快適にウェブサービス使えるのは当たり前だし,この辺にコミットするために計算量ベンリ
  • Q&A
    • from yuuki: このへんミスったりすると自律制御したりしても一瞬でリソース食いつぶしたりするし,このへん自律制御するのどうするかとかもおもしろそう

べんり ホーム - 鳥獣戯画制作キット

計算量の感覚大事.

STNS 〜点と線を結び新しい何かを作るコト〜

15:25 | pyama(ペパボ) | STNS 〜点と線を結び新しい何かを作るコト〜 | 25分

  • やましたさん. @pyama86
    • ムームードメインやってる
  • Linux のユーザ管理
    • いつから LDAP 主流だと錯覚してい(ry
  • 最近のユーザ管理
    • root おおい.
  • rootは問題あるよね
    • セキュリティ事故の追跡
    • sudo権限の分離
    • userの追加削除管理困難.追加でポリシーのため他のサーバにも足す…とかやるとこまる.
    • rootはアブナイ!!!
  • でもなぜやってしまうか
    • なにかあったときしか困らない
    • まぁLDAP構築たいへんだよねとかある.
  • STNS で解決!
    • STNS/STNS: Simple Toml Name Service
    • 名前解決/公開鍵取得/アカウント認証のみを提供.LDAPはいろいろできすぎて困る.
    • ls -ltr の名前は実はid. pyama -> id:1000 .これが名前解決
  • デプロイユーザの管理できる
    • capistorano とか公開鍵たしてsshでやるよね.authorized_keys 管理だるくなるよね.
    • stnsだとスッキリ!誰がdeployできるか一目瞭然でよい.
  • 組織構造を表現できる
    • group
  • シュッとインストールできるよ! 2.5min
  • 事例
    • pepaboさん事例.ユーザ管理もgithub flowで. ghe でpr -> droneでテスト & レビュー -> deploy
    • 承認してマネージャーが承認して…とかめんどくてそれ解決できてベンリ.エンジニアで管理
    • ghe で全部管理できるので入退社管理とかも楽
  • プロダクトを運用すること
    • ヒントとなった技術からアイデア得たり
    • mackerelのtomlとかgo使ってるやつ参考にしたり
    • linuxで利用可能な共通ライブラリがgo1.5から作れるようになってこれがでかい.Cを書かなくてもLinuxのシステムに手を入れられる
    • 自分が開発者だし自分がSTNSを最高にできる!!!

LDAP とかユーザ管理あんまり関わってないけど便利そうだった.良い話きけて良い.

  • Q&A:
    • from yuuki: hatena は LDAP だけどSTNSよさそう!

負荷分散技術を選ぶ時に考えること

15:55 | masayoshi(はてな) | 負荷分散技術を選ぶ時に考えること | 25分

負荷分散技術を選ぶときに考えること // Speaker Deck

  • masayoshi @yoyogidesaiz
  • 負荷分散技術の概要
    • データセンター分散したり
    • ロードバランサーでbackend web分散したり
    • サーバ内/ロールごと/サーバごと のだいたい3つの分散ある
  • サーバ内リソースの負荷分散
    • ハードウェア機能: hyper-threading, raid0
    • ハードウェア意識のOSの負荷分散: numa, rss/rfs/rps
    • OS意識のアプリケーションの作り方: fork()/clone() などのシステムコール
    • Numa NUMA - Wikipedia
      • NUMA(Non-Uniform Memory Access、ヌマ)とは、共有メモリ型マルチプロセッサコンピュータシステムのアーキテクチャのひとつで、複数プロセッサが共有するメインメモリへのアクセスコストが、メモリ領域とプロセッサに依存して均一でないアーキテクチャである – NUMA - Wikipedia

    • application
      • fork() プロセス
      • clone() スレッド
      • select() プロセス <- x (io多重化とかに影響するだけでCPUには影響しない?)
      • このへんいろいろ理解してアプリケーションコードかく! (なるほど)
  • ロールごとの分散
    • proxy/web/db などのロールの分散
    • proxyでキャッシュしたり,全部のリクエストがdbまで到達しないようにとか
    • キャッシュ
      • ユーザに近いところで返す
      • キャッシュヒットしなくて破綻とか実装に無理があったりとかもする.
      • -> 使いどころを見極める.キャッシュは麻薬
  • サーバごとの負荷分散
  • まとめ
  • Q&A
    • どこが負荷おおいか?
      • disk がおおい.dbとか.ロールごとに分けておいてキャッシュ聞かせていく戦略おおい.(計算機の仕組み的にdiskがおそい from yuuki).最近iodriveとかあって速くなってきてるのでスケールアップが多い.

サービスに寄り添うログ基盤 - ログ収集のその先に -

16:20 | monochromegane(ペパボ) | サービスに寄り添うログ基盤 - ログ収集のその先に - | 25分

サービスに寄り添うログ基盤/pepabo_log_infrastructure_bigfoot // Speaker Deck

  • monochromegane
    • minne
    • 普段 rails 書いてる.最近ログ基盤の開発してる.
  • ログはいいぞ!
    • ログはウェブサービスにおいて重要
  • 行動ログ
    • アプリケーション層で出力するログ(apacheのログとかではない)
    • いつ,だれが,なにをやったか特定できる
    • 最終結果だけでなく,どこであきらめたか.どう迷ったかが分かる
      • 特にどこであきらめたか.どう迷ったかが分かるところにサービス改善のヒントが詰まってる!!!

  • 行動ログ活用段階
    • 収集: とりあとめる
    • 分析: 視覚化したり分析
    • 活用: 分析結果を使って継続的なサービス改善
    • “ログの活用”
      • ログがたまるだけとか,グラフでてバンザイ!するだけではだめ!!
    • -> ログの活用基盤をつくる!
  • Bigfoot
    • ペパボの次世代ログ活用基盤
    • minnneのそれでもある.
    • UID 振る.アプリでログを吐いて集約基盤へ -> 分析 -> サービス改善など活用
  • Bigfoot を支える技術
    • ログを送る
      • fluentd rack-bigfoot(rails) OSS的な感じではなさそうか…?
    • 集約基盤 Treasure Data
      • 活用に力入れたかったので集約基盤はとりあえずTDに任せた.あとで自社のものにするかも
      • Hive QL. 行動ログをSQLライクに扱える
    • ワークフロー
    • 属性情報
      • 行動ログのidから性別などなど属性情報を組み合わせると分析の幅が広がる
    • 名寄せ
      • サービスのアカウントと各クライアントをマッピング
      • 未ログイン状態のアカウントも名寄せ後に過去に遡って紐付け
      • cookie syncと組み合わせてサービス間の紐付け
    • Big Cube とCube
      • BigCube: 全サービスの行動ログを集約してる
      • 切り口が確定したらCubeに切り出す(cubeに切り出されるとpostgresに入るので速く集計できたりする)
    • 視覚化と分析
    • 活用
      • 画面デザインの変更.ステップ見直し
      • A/Bテスト
      • -> 静的なフィードバック.人が判断.固定化する.
    • 動的なフィードバックがよいのでは?
      • システムが行動ログを吐く -> 変換したものをシステムが受け取る -> 挙動を変える
      • バンディットアルゴリズム
      • リコメンド
        • matrix factorization
        • 強調フィルタリングの一種
        • tdのなんかでできるらしい?
    • browse,card abondonment
  • サービスに寄り添うログ基盤
    • 単に集めるだけじゃなくて分析,活用の段階を補助する
    • 静的フィードバックから動的フィードバックへ
    • 行動ログの循環によってなめらかな世界へ.ということでログはいいぞ
  • Q&A
    • Q「送る側のサービスからログ基盤への負荷の問題はどうか」A「fluentdがよく出来ているから問題ない」 https://twitter.com/matsumotory/status/749151437850980352
    • Q「fluentd自体の負荷はどうか」A「ない、今の設計規模では大丈夫」もともとfluentd自体はつかってて大丈夫ならしい
    • td負荷? ログを送りつけるぶんには負荷は気にしなくて良い.送ったあとにインデックス使わずに集計したりするとまずい.プランやすかったりすると特に.

まじか…

活用を重要視していてよさそう.おもしろい話だった.

「ログはいいぞ」.

若手インフラ座談会

16:55 | masayoshi(はてな) taketo957(はてな) alotofwe(ペパボ) hanazuki(ペパボ) モデレータ stanaka(はてな) | 若手インフラ座談会 | 40分

  • 新卒1,2年目の人達で座談会.stanakaさん仕切ってる
  • 自己紹介
  • なんでインフラ?
    • masayoshi: ネットワーク系の研究してたり.かっこいいじゃん?
    • hanazuki: KMC入ってた.サーバーいじったりするの楽しかった.
    • taketo957: B3くらいでRailsやってたらブラックボックスおおくていろいろ調べてた.京都ならはてなでインフラできそうということでアルバイトしてisuconしたりなどなど.面白くてそういう形式で入社した.
    • alotofwe: 大学時代はそんなにインフラしてたわけじゃなかった.アプリは書いていたけど,やっていてアプリはもういいやという感じになった.インフラorセキュリティやろうとおもって,セキュリティ志望だけどセキュリティするためにはインフラ知らなきゃだめなので今インフラやってる
        1. せきゅりてぃ専門のひとpepaboにいる?
        1. ちょっといる.matsumotoryさんとかも?
      • はてなではセキュリティ専門はいない.みんなでやる.
  • アプリとインフラの境界? たとえばDBへのクエリ,スキーマあたりの責任や分担とかどう?
    • masayoshi: 監視業務のアルバイトしてその時はじめてインフラやった.そのときはコード書いてる人はいなかった.DBの設計まではしないけど性能のチェック,クエリのパフォーマンスチェックなどはしてた.はてなでは? -> だいたい一緒.
    • taketo957: 入社以前はもっとハッキリした境界あると思ってたけど,入ってみたらアプリ側が一緒にやってくれたりとか.インフラはmiddle wareより下はだいたいみてる.
    • hanazuki: パフォーマンスチューニングとかが境界.どっちからもみる.上からみるか下からみるかって感じ.境界がハッキリはしてない.
    • alotofwe: だいたいhanazukiさんと同じ.開発のひとからpull-reqが飛んできてレビューするとかまであるくらい境界は曖昧.ある程度権限はあるけどソレ以外はほとんど境界はない.
  • インフラエンジニアになって1-2年,おもしろかったことや印象的なエピソードとかある?
    • masayoshi: はてなはオンプレ環境ある.ネットワーク機器をみてエラーパケットとかみたりした.そこで傾向とかがみれて面白い
    • hanazuki: プライベートクラウド使ってる.チョット前まではオンプレ.仮想環境を使う側.awsを使うのとは違ってどう動かすかとかツールとか作っていく.この辺が楽しい
    • taketo957: いろいろわかってきて嬉しい!
    • alotofwe: 推理小説がスキ.障害の何が原因か調べるのが探偵の推理っぽくて楽しい.
  • 研修でよかったこと
    • taketo957: 今年からインフラでも新卒研修.知識編と設計編.設計編がおもしろかった.実際に動いてるサービスにたいしてこのくらいのリクエストならどう設計するか.身になる部分でよかった.
    • hanazuki: 1ヶ月間くらい研修ある.内容自体はだいたい知ってたりもしたけど試行錯誤がおもしろかった.
    • alotofwe: 今年は研修作る側.内容: railsつくって運用基盤つくってmobileつくる.最低限の生き延びるための知識を得るようなもの.インフラのものはあまり知らなかったので特に勉強になった.
    • masayoshi: 全部taketoくんに言われた! ミドルウェアの組み合わせだけじゃなくて構築するとかコードを書いて作ってみるとどこがボトルネックになるのかとかわかったりする.作ったり構築・コード書くのも研修でやるとその辺に気づけて勉強になるのでベンリ.
  • hatena は京都と東京.pepaboは福岡と東京にある.2拠点でやってることに関して感じることとか?
    • taketo957: 自分がやった話ではない.東京とのコミュニケーションコストを下げる.提示前15minのslack call雑談とかやってる.(yuukiさんが導入した)
    • masayoshi: taketoさんの続きってかんじ.今すぐ,まだまとまってないけど考えを話し合い,そういうときに音声チャットあってすぐに話せる環境があるとよい.ちょっと話したいけどいいですか?って聞いたらすぐ聞けるという環境が大事でベンリ.
    • taketo957: 補足.はてなは社内の文化的にこんなことも残すのか.というところまで残す.音声もベンリだけどチャットなどのテキストで何でも残すというところもよい.
    • hanazuki: みてるサービスが違うのでそこまでコミュニケーションをする必要はそもそもない.週1でビデオコールとかしてる.コミュニケーションとりたいけど取れないときもあるのでなんとかしたい.
    • alotofwe: slackべんり.アイコンが顔写真でよい.
    • masayoshi: アイコンもよいよね!
    • どうしても落ちがちな情報.手元で詰まってるけど大変とかいう情報とか.
  • ロールモデル.将来どうなりたいとか.社内社外問わず目標としてる人とかいるか?
    • masayoshi: 具体的な人物とかはあんまりない.エンジニアとアカデミック系では本来あんまり境界はない.インフラのパフォーマンスチューニングとかは個人の技術という側面がおおいので体系化して学術分野にも広めたりアウトプットしたい.
    • taketo957: 入社したときはyuukiさんにあこがれてといった.ネットワーク周り喋ってるひとがおおい.アプリ観点から観てるひとはあんまりすくなさそう.研究室でやってきた人力でやる仕組みとか応用したりしていきたい.(クラウドソーシング?)
    • hanazuki: あんまり決まってない.人力の認知力でやったりするのはうっかりとかが発生して困るのでつらい.半分寝てても仕事できるようにしたい
    • alotofwe: よくばりさんなので側面によって尊敬してる人が異なる.つまみ食いしていきたい.食べてる最中なのであんまり決まってない.
  • インフラエンジニアの醍醐味?.会社のいいところは?
    • taketo957: レイヤーが下がるにつれて相手にするものが多くなる.それにつれて自分の知識も増やす必要がある.いろんな知識を裏側まで見通してやっていったりするのは面白い.会社のよいところ.新しい技術・古い技術と幅がでていてよい.
    • masayoshi: 基盤をつくるのが面白い.大規模なものを支えるところが面白い.裏方だけど支えがないと動かない.このアラート放置していいんすか?とか聞くと先輩とかが話してくれて一緒に解決してくれたり.
    • hanazuki: インフラといってもハードウェアみたりチューニングしたりなどいろいろな分野・仕事がある.いろいろできるのよい.それぞれスキなレイヤで改善できるところとかよい.
    • alotofwe: アプリと比較.アプリ開発だと適当に書いても動いちゃう.インフラだと1行追加すると大きい影響があってじっくり考慮してかかなきゃだめだったりする.向上心強い人がおおい.よくしていきたいという気持ち.勉強しやすい会社.

僕の(雑)まとめ感想とか

インフラ系のことはほとんどできていなくて,知識も全然ないけど,どんな感じでやってるのかなぁと興味はあったので参加しました. アプリケーション書くときもインフラ意識して書くとよかったりするのでインフラエンジニアとかウェブオペレーションエンジニアみたいな職種につかなくても知っておくと便利. 実際座談会の話では,はてなさんでもペパボさんでもアプリケーションエンジニアとインフラエンジニアの仕事の境界とかは曖昧で,上から見るか下から見るかの違い程度しかないみたいな話をしてた気がする. 僕も,もっとインフラ意識しながら開発していきたいなーという気持ち高まった.

ネットワーク周りだとシステムコールとかいろいろ正直よくわからんくて前提知識僕が持ってないんだなーという話は多かったけど, わかんない話でもおもしろいなーと得られる部分あったり,割とまだ分かる話(相対的に)でも知らないことがたくさん学べたり,なるほどなーとかそうだよなーよいよい!という話ばかりで どの発表もよくて来てよかった.

運営・発表者の皆さんありがとうございました.

6/2までKindle本50%オフセール!IT系の本で僕が欲しい本をまとめた!!!

2016年5月27日(金)00時00分~2016年6月2日(木)23時59分(日本時間)まで Kindle 50%OFF セール をやっているらしく,コンピュータ・IT系の本で僕が欲しい!!!よさそう!!!と思った本をまとめました.

先日 Kindle Paperwhite Wi-Fi を買った勢としてはこのKindle セールに乗るしかない!!! 積んでいた Soft skills の原著をKindle paperwhite で最近読んでますが,paperwhite かなり読みやすくて感動してます. いくつか固定レイアウト型の本がセールになってて, paperwhite で読むのはそこまでよさそうでもないけどそんなことは気にしない.

なおまとめてみると全部ポイント還元ではなく50%OFFセール本でした. 基本的にここから集めました. Amazon.co.jp: コンピュータ・IT - Kindle本: Kindleストア

かなり欲しい!!!というか多分買う本

昔,図書館で借りてたけど途中で返しちゃった.プロコンでオススメの本といえば蟻本が必ず上がるし欲しい! プロコン最近やってないけど時間とってやりたい…

(途中までしか読めてないけど)蟻本よかったしセキュリティコンテスト版もよいでしょ.という気持ち.CTFどんなもんか気になる.

去年インターンの面接の対策として物理本を借りて読んだ.コーディング面接…?なにそれ…?という状態の自分にとってめっちゃよかった.読んだことあるけど手元にKindle本としてあってもよいかも.

「世界で闘うプログラミング力を鍛える150問 トップIT企業のプログラマになるための本」がよくて,プロジェクトマネージャー版がでるとの噂を聞いて本屋でちらっと立ち読みした. 全然内容覚えてないけどよさそうな雰囲気だったので欲しい.

名著感.確かちょっと読んだことがあるのは情熱プログラマーで,闘うプログラマーの方は読んだことなかった.よさそうなので欲しい.情熱プログラマーはKindle版がそもそもなかった…洋書版ならあるけど…洋書版セールじゃないけどほしいな.

レガシーコード改善ガイド
翔泳社 (2016-01-15)
売り上げランキング: 264

聞いたことある名著感.レガシーコード改善したいし,今回のセールで一番欲しいかも知れない.(上記に挙げてる本はほとんど固定レイアウトだし…) レガシーコード改善ガイドを読んで vim-easymotion といった割とレガシーなメンテしてるプロダクトをリファクタリングするゾ!!!という気持ち.

買うか迷ってるけど欲しい!!!本

プログラミングコンテスト攻略のためのアルゴリズムとデータ構造
マイナビ出版 (2015-01-30)
売り上げランキング: 383

プロコンとかアルゴリズム本の文脈でたまに聞く.ちらっと本屋で立ち読みしたことがあった気がするけどよさそうだった.

オンラインジャッジではじめるC/C++プログラミング入門
マイナビ出版 (2014-06-28)
売り上げランキング: 6,224

C/C++わかってなくて,オンラインジャッジでやれるところがよさそう.C言語学んで Vim のコードベースにコントリビュートするゾ!!!という気持ち.

TCP/IP の基礎
TCP/IP の基礎
posted with amazlet at 16.05.30
マイナビ出版 (2011-02-23)
売り上げランキング: 18,345

TCP/IP,よくみる有名な本ではないけど,評価も高そうだし基礎として読みたい.

徳丸浩のWebセキュリティ教室(日経BP Next ICT選書)
日経BP社 (2015-11-10)
売り上げランキング: 86

自分が書いたコードが知らないうちに脆弱性持ってたりすると怖いし,セキュリティ系は知識として知っておくと便利そう.

世界でもっとも強力な9のアルゴリズム
日経BP社 (2013-10-10)
売り上げランキング: 246

聞いたことあるし読み物として面白そう?

Webエンジニアが知っておきたいインフラの基本
マイナビ出版 (2014-12-27)
売り上げランキング: 990

インフラ,わかってないので基本を知りたい!

コンピュータの構成と設計 第5版 上
日経BP社 (2015-02-25)
売り上げランキング: 484

「パタ&へネ」本.名著感.この辺の知識全然なさそうなので読むと便利そう.「ヘネパタ」本はセールじゃなかった…

コンピュータの構成と設計 第5版 下
日経BP社 (2015-02-25)
売り上げランキング: 475
OSの仕組みの絵本
OSの仕組みの絵本
posted with amazlet at 16.05.30
翔泳社 (2013-05-20)
売り上げランキング: 6,184

OSの仕組みに関する知識も全然もってないのでよさそう.

「なぜなのか」系

コンピュータはなぜ動くのかは昔読んだことあってよかった. なのでこの「なぜなのか」系統の本はよさそうというイメージ. 「なぜなのか」系は他にもセールだったけど気になるタイトルだけ抜粋.

オブジェクト指向でなぜつくるのか 第2版
日経BP社 (2014-03-05)
売り上げランキング: 114
システムはなぜダウンするのか
日経BP社 (2014-03-05)
売り上げランキング: 493

ちょっと欲しい気もする

ピープルウエア 第3版
日経BP社 (2014-02-05)
売り上げランキング: 339

聴いたことあるし名著っぽいので

テストから見えてくるグーグルのソフトウェア開発
日経BP社 (2014-02-12)
売り上げランキング: 5,657
Linuxサーバーセキュリティ徹底入門
翔泳社 (2013-11-12)
売り上げランキング: 4,856

サーバのセキュリティ,ちょっとくらい知っておいても損はなさそう.

Docker わかってないので知っておきたい.

ソーシャル・エンジニアリング
日経BP社 (2013-08-28)
売り上げランキング: 4,286

セキュリティ系は知っておいて損がなさそう.

持ってるけどオススメ!本

持ってるけどまだ読んだとは言ってない! 読みたい!!!

技術書・ビジネス書 大賞 部門

ITエンジニアに読んでほしい!技術書・ビジネス書 大賞 2016 に含まれている本.Kindle セールになってるの2つしかなかったけど.

HARD THINGS 答えがない難問と困難にきみはどう立ち向かうか
日経BP社 (2015-04-17)
売り上げランキング: 14

おすすめされた. 2015年の電子書籍で一番売れたとか評判よさそうだし読み物として買いたい.

21世紀のビジネスにデザイン思考が必要な理由
クロスメディア・パブリッシング(インプレス) (2015-07-22)
売り上げランキング: 214

55%なので6/2までのセール対象というわけではないかも.

追記.記事書いた後に見つけた本

おわりに. テンプレ的な何か

Amazonギフト券- Eメールタイプ - Amazon Kindle
Amazonギフト券 (2012-12-10)
売り上げランキング: 17

Kindle 本は欲しいものリストでプレゼントできないらしいですが,Amazon ギフト券で (hayabusa1419 at gmail.com) にプレゼントしてくれてもいいですよ???

revital.vim で vital.vim を爆速にしてお前らの Vim Plugin を速くする

haya14busa/revital.vim

この度, revital.vim というプラグインを作って vital.vim のモジュールのローディングを爆速にしてお前らが使ってる Vim plugin を速くしました.

めでたい.

あと気づいたんですが今日は僕の誕生日のですね.これもまためでたい.

そして本当のところは vital.vim を使ってるプラグイン開発者が, revital.vim を使って初めて速くなるので実はまだ速くなってないものが多いです. 待ちきれない方はこの記事を読んで revital.vim の使い方を覚えてプルリクしていきましょう. また爆速にはなったと思うんですが,体感には個人差・環境差があり,もともとほとんど速度が気にならない人も多いかと思うのでご注意ください. Windows だか symlink だか virtualbox だか neovim だか何かはまだよくわかってませんが,特定の 環境が原因なのか vital.vim をヘビーに使用しているプラグインにまれによく「遅いぞ?」という issue が飛んできたりしていて, そういった方には顕著に効果があると思います.(たぶん)

参考: 遅いと言ってる人たち (放置気味でスイマセン…いや workaround な修正なら前からできたんだけど手元でも再現しないものをその場対処はあんまりやりたくなくてやる気が…)

vital.vim とは?

https://github.com/vim-jp/vital.vim

Vim script の最高のライブラリです.vital.vimのいいところとダメなところを個人的に上げるとこんな感じです.

vital.vim のいいところ

  1. 組み込み式なので依存ライブラリがアップデートされても安心
  2. プラグインのユーザはvital.vimを別途インストールする必要がない
  3. めっちゃ気軽に外部ライブラリを作って使える
  4. けっこういろんなものがそろっていて種類が豊富
  5. 日本人の凄腕 Vimmer 達が開発・メンテしているので品質も高い

とにかくベンリ

vital.vim のダメなところ

  1. (ロードが) 遅い (ケースがある)(基本的に気にならないけど)
  2. ドキュメントがたぶん足りないので敷居が高い(ように見えるだけで使い方は簡単なんだけど…)
  3. インストールやアップデートでハマることが多い印象

他のところで,ファイルをコピーするのが無駄だとかキッチンシンクじゃない?みたいな 話を聞いたことがありますが,前者は全然気にする時代じゃないはずだし,後者は単なる勘違いで vital.vim は使うライブラリのみ組み込めるので問題ないはずです.

Githubのリポジトリでは

This is like a plugin which has both aspects of Bundler and jQuery at the same time.

と(たぶん昔から)書いてあって,Bundler はともかく jQuery はちょっとあんまり良い印象ではないのかなぁと思う. どちらかというと lodash とか Bundler に合わせるなら npm と言ってもいい気がする.

で,話が少々それていますが,今回 1つ目のモジュールの読み込みが遅いという部分を revital.vim で解決してみました. 2と3はドキュメントを拡充したり,:Vitalizerというコマンドをもうちょっとユーザフレンドリーにしてあげるといいのかなぁと個人的に思うのでなんとかしたいと思います. (去年くらい前から思っているのでつらい)

とにかく vital.vim 最高なので revital.vim と一緒に使っていきましょう.

速くなったというならまずはベンチマークじゃん?(雑)

スクリプト

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
command! -bar TimerStart let start_time = reltime()
command! -bar TimerEnd echo reltimestr(reltime(start_time)) | unlet start_time

function! s:_vital_of() abort
  let V = vital#of('incsearch')
  call V.load('Data.List')
  call V.unload()
endfunction

function! s:_vital_incsearch_of() abort
  let V = vital#incsearch#of()
  call V.load('Data.List')
  call V.unload()
endfunction

let s:times = 100

TimerStart
for _ in range(s:times)
  call s:_vital_of()
endfor
TimerEnd
" => 1.565324

TimerStart
for _ in range(s:times)
  call s:_vital_incsearch_of()
endfor
TimerEnd
" => 0.028437

結果: vital#of() と V.import(‘Data.List’) 相当を100回回したベンチマーク

vital.vim (x 100) revital.vim (x 100)
1.565324 sec 0.028437 sec

ref: https://github.com/haya14busa/incsearch.vim/pull/112#issue-142680963

速くなってますね!!!

(まぁ僕の環境ではもともと1回分にすると0.01秒くらいで全然遅いと感じたことなかったのですが)

上記のベンチマークは https://github.com/haya14busa/incsearch.vim のコードで回しましたが,https://github.com/easymotion/vim-easymotion や 手元でテスト用に作った全部のvital モジュールをインストールしたプラグインでも同じような結果になりました.

revital.vim の使い方

さぁこれだけ速くなってるならvital.vimを既に使ってる人なんかは特に revital.vim を使ってみたくなりましたよね? 使い方は簡単です.

わかってる人向けの簡単説明

  1. vital.vim で :Vitalize しておく
  2. revital.vim の :Revitalize コマンドを実行
  3. vital#of('{plugin-name}') の変わりに vital#{plugin-name}#of()を使う.

これだけです.インターフェースは vital.vim をそのまま使う場合とほとんど変わりません.

ちょっと丁寧な説明

a) モジュールをインストール

{pluginname} をあなたかが開発しているプラグインの名前に置き換えましょう.

  1. :cd /path/to/your/plugin プラグインのディレクトリに移動.もちろん shell で移動してから Vim を起動するとかコマンドで指定してもOK.
  2. :Vitalize --name={pluginname} . +Data.List Data.List モジュールを組み込んでみる
  3. --nameには.-が使えないので適宜vim-とか.vimとかいらない部分は削る.
  4. :Revitalize . Revitalize 実行!

b) モジュールの使い方

1
2
3
4
let s:V = vital#{pluginname}#of()
let s:List = s:V.import('Data.List')
echo s:List.uniq([1, 1, 2, 3, 1, 2])
" => [1, 2, 3]

簡単で vital.vim のみで使うケースとほとんど変わりません.

c) モジュールのアップデート

:Vitalizeでアップデートしたあとにもう一度 :Revitalize する必要があります.

  1. :cd /path/to/your/plugin プラグインのディレクトリに移動.
  2. :Vitalize . アップデートするときはこれだけ.
  3. :Revitalize . Revitalize 実行

どうして revitalize.vim は速いのか?

vital.vim はモジュールをロードする際(s:V.import('Module.Name'))に

  1. モジュール名から目的のファイルを探す
  2. そのファイルからモジュール用のオブジェクトを作る

というざっくり2段階が必要です.このうち1などはsimlinkをたどるといった関数が遅 いせいで結構な時間が環境によってはかかっていますし,2はそこまで遅くはない気もし ますがいろいろ内部でやっています.(ちゃんとprofileはしてない.) vital.vim の組み込みライブラリであるという性質上,普通にやるなら上記の段階が必要です. また歴史的経緯も含まれているかもしれないですが上記の2段階の前にはライブラリを ロードするためのローダーを同じような手順で作成する必要があります(vital#of({plugin-name})).

速くする方法はないものかなぁと考えると1つ思い当たります.

モジュール名から目的のファイルを Vim script で素早く探すのにはなかなか骨が折れますが,Vim script には autoload function という機能があり,autoload 関数をいい感じに定義しいい感じに呼 べば(path#to#module#file),対応したファイルを勝手に内部で見つけてきて関数を呼 んでくれるという仕組みが存在します.Vim script で頑張るよりも組み込み機能を 使ったほうが速いはずです!! autoload 関数使いたい!!!

しかし,autoload 関数をいい感じに定義する際にはファイルのパス情報が必要になります. ここでvital.vim は別のプラグインに組み込まれることが前提のライブラリなのでパスが定まっていません. よって autoload はそのままでは使えませんでした…

うーん.困ったな…

でもでも,よくよく考えてみると最初からパスが定まっていなくても,モジュールをプラグインに組み込んだあとのパスは決定しています. つまり,:Vitalize でモジュールをプラグインに組み込んだあとにモジュールのファイルに適切な autoload 関数を追加してしまえばいいのです.

もうわかったでしょか?

revital.vim が提供する :Revitalize コマンドは組み込んだモジュールのファイルに 適切なautoload関数を追加し, s:V.import('Module.Name') の内部では追加した autoload 関数を呼ぶようになっているのです. また,autoload関数を追加する際にモジュールのオブジェクトの雛形となるようなオブジェクトをついでに生成してやっているので, そのオブジェクトの生成するプロセス分も速くなっています.

最後にファイルを探したりといろいろと大変な vital#of({plugin-name}) の代わりに 直接 vital のローダーオブジェクトを返す vital#{plugin-name}#of() を作って revital.vim の仕事は終了です.

モジュールのファイルに autoload 関数を追加するというちょっと刺激的なハックをすることによって vital.vim のロードを爆速化することができました. ただモジュールのファイルといっても組み込んだあとのモジュールのファイルを書き換 えるだけなのでオリジナルのファイルは書き換えないし,これくらいのハックは別に問題ないかなと思います. 一応vitalモジュールのファイルの途中で :finish されると使えなくなるという問題がありますが,まずそんなケースはないでしょう.

本家に入れたいような気もするけど要相談?

確実に速くなるし,本家ではテストされてないような部分もテストしているので,少々 ランニングして安定すれば本家にオプションかなにかで入れてもいいんじゃないかなぁと思います.

しかし,一応入り口のインターフェースが変わることと,ちょっと実装にハック感があ ること,ドラスティックな変更なのでいろいろ待つよりもまずは実装して見てみるということで revital.vim を作ってみました.

後方互換性は崩さないような仕組みになっているので時が来たらvital.vim 本家に同じ機能が実装されるとよさがありますね.

おわり

haya14busa/revital.vim で vital.vim が爆速になるので vital.vim を使っている Vim プラグイン開発者各位や これから vital.vim を使ってみたいという 各位は是非お試しください!

「爆ぜろリアル! 弾けろシナプス! Rev!talize Th!s World!」