grpc-web-clientをjsで試してみた

gRPC-Web: Moving past REST+JSON towards type-safe Web APIs - Improbableを見て、grpcwebを使えばgoogle.golang.org/grpc製の既存gRPCサーバがブラウザからも叩けるようになるとのことなので試してみた。

github.com

サーバ側の変更点

DOC.mdにも書いてあるように

の2点を行うだけ。

diff --git a/backend/main.go b/backend/main.go
index 0f230c4..f261ab9 100644
--- a/backend/main.go
+++ b/backend/main.go
@@ -2,8 +2,9 @@ package main
 
 import (
    "log"
-  "net"
+   "net/http"
 
+   "github.com/improbable-eng/grpc-web/go/grpcweb"
    "golang.org/x/net/context"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials"
@@ -30,11 +31,15 @@ func main() {
    gs := grpc.NewServer(opts...)
    pb.RegisterEchoServer(gs, &server{})
 
-  l, err := net.Listen("tcp", addr)
-  if err != nil {
-      log.Fatal(err)
+   ws := grpcweb.WrapServer(gs)
+
+   mux := http.NewServeMux()
+   mux.Handle("/", http.HandlerFunc(ws.ServeHttp))
+   hs := &http.Server{
+       Addr:    addr,
+       Handler: mux,
    }
 
-  log.Println("Starting server on", l.Addr())
-  log.Println(gs.Serve(l))
+   log.Println("Starting server on", hs.Addr)
+   log.Println(hs.ListenAndServeTLS("./certs/cert.pem", "./certs/key.pem"))
 }

ブラウザ側の実装

サンプルはTypeScriptだけど、JavaScriptでも書けるみたいなのでES6でやってみた。

1. まずはprotocのプラグインts-protoc-genをインストールする
npm install --save-dev ts-protoc-gen

これで以下のように.protoからJavaScriptの定義ファイルが生成できるようになる。

protoc --plugin=protoc-gen-js_service=./node_modules/.bin/protoc-gen-js_service \
--js_out=import_style=commonjs,binary:. \
--js_service_out=. \
pb/*.proto

js_outで生成されるのが.protoのmessage
js_service_outで生成されるのが.protoのserviceになっていた。

2. 次にクライアントライブラリのgrpc-web-clientをインストールする
npm install --save google-protobuf @types/google-protobuf grpc-web-client

使い方はgrpc-web-clientのinvoke()に第1引数としてjs_service_outのrpc、第2引数としてリクエスト、接続先、各種コールバック関数をオブジェクトで渡す形になる。

import {grpc} from "grpc-web-client";

import {Echo} from "../pb/echo_pb_service.js";
import {Request} from "../pb/echo_pb.js";

function EchoCall(value) {
  const req = new Request();
  req.setValue(value);

  grpc.invoke(Echo.Call, {
    request: req,
    host: "https://localhost:9090",
    onMessage: (message) => {
      console.log("onMessage", message.toObject());
      alert(message.getValue());
    },
    onEnd: (code, msg, trailers) => {
      console.log("onEnd", code, msg, trailers);
    }
  });
}

// ちゃんと動けば引数の文字列がダイアログに出てくる
EchoCall("Hello grpc-web-client");

リクエストやレスポンスなどの各フィールドには基本的にgetterとsetterを通してアクセスすることになるみたい。

既存クライアントへの影響

気になるのは既存クライアントがどうなるのかというところ。
grpc.DialOptionの認証情報の有無で見てみると次のような結果になった。

grpc.WithInsecure()
メソッド \ サーバオプション 無し grpc.Creds()
ListenAndServe() X X
ListenAndServeTLS() X X
grpc.WithTransportCredentials()
メソッド \ サーバオプション 無し grpc.Creds()
ListenAndServe() X X
ListenAndServeTLS() O O

つまりクライアントはgrpc.WithTransportCredentials()が必須になり、grpc.Serverのオプションに関わらずListenAndServeTLS()を使えば良いということになる。
(grpc.WithInsecure()を使っていたらクライアントを直すなりサーバを分けるなりしないといけない)

まとめ

サーバ側はけっこう簡単にブラウザ対応できるし、
grpc-gatewayと比べると

が不要になるので管理するものが減って少し楽になりそう。

けど証明書が必要になるのはローカルでの動作確認とかがちょっと面倒になるかも…

まあフロントエンド的にはswaggerで生成するかprotocで生成するかの違いなので実際どっちでも良かったりするのかな?

今更だけどLGL22をIIJmioで使い始めた

LGL22はそこそこ古い機種で、もう3年くらい使っているけど
色々とあって未だにこれを使っている。 www.lg.com

理由の1つとしてIIJmioのタイプAを待っていたっていうのもあるんだけど、
タイプAはVoLTE対応機じゃないと使えないので非対応のLGL22はアウツ…

なので結局タイプDにすることにした。

流れとしては、

1. MNP予約番号の取得

0077-75470 に電話してMNP予約番号を発行してもらう。
電話で伝えてもらえるけど後からSMSも送られてくるのでメモとか無くても大丈夫。

2. SIMロックの解除

以下のサイトからアンロックコードを取得する。

https://sim-unlock.net/jp/simlock/LG/LGL22/

画面には*#06#でIMEIを調べてくださいと書いてあったけど1桁足りないので、

設定 → 一般 → 端末情報 → ステータス

に表示されているIMEIを入力した。
たしか入力してから5分くらいでメールが送られてきたと思う。

送られてきたNCKは

2945#*22# -> ネットワークロック

から入力する。

3. IIJmioの申し込み

普通にWebから申し込む。
SIMカードのサイズはnanoSIMを選択。

4. 回線の切り替え

実際にSIMが届いたのは申し込みから3日後だった。
IIJmioオンデマンド開通センター」に電話して回線を切り替える。
時間が19:00までなのに気づいたのが18:56だったけどなんとか間に合った。

その後は

3845*#22# -> KDDI Only -> Network Setting -> Network Mode Change

からLTE/CDMA/GSM/WCDMAを選択して、

設定 -> テザリングとネットワーク -> モバイルネットワーク -> アクセスポイント名 -> 手動設定

からAPNを設定する。
いつ切り替わったか覚えていないけど10分後には使えるようになっていた。
電話の発着信も問題無し。

2週間ちょい使ってみて

Band1 Onlyなのが少し不安だったけど都内で生活する分には全然問題無かった。
クーポンOFFだと使い物にならない時もあるけど今の所そこまで困っていない。

エンジニアにジョブチェンジしてやってきたこと

「君のスキルはウチの新人と同レベルだけど、そんなんでやっていけるの?」と言われて今の会社に入社することを決めたのはもう4年半ほど前のこと。
前職はテスターでコードは全然書けなかったしデータベースとかも触ったことなかったけど好き勝手やらせてもらった結果、それなりのエンジニアに成長することができたと思う。
それも今月いっぱいで退職なのでちょうど良い機会だし自分じゃないとできなかった(やらなかった)ようなことを中心にざっくり振り返ってみる。
※イマイチだったことは全部書いていくとキリがないので省略

Perl(CGI + 生DBI)製Webシステムの改善

Template-toolkitをwrapするPerlモジュールを作った
  • HTMLがscriptタグも含めて1行ずつ丁寧にprintされていたのでメンテナンスが辛かった
  • SQLも文字列連結で組み立てられていたり、無理矢理1行に詰め込まれていたりしたのでメンテナンスが辛かった
  • Perlのバージョンが古くて(たしか5.8)フレームワークの導入も難しい状況だったのでとりあえずTemplate Toolkitで凌ぐことにした
    • HTMLは標準出力に吐き出してテンプレート化
    • SQLVim scriptで.cgiから抽出してテンプレート化
  • Perlモジュールにしたのは各.cgiで統一的なコードが書けるようにしたかったから
DBアクセス用のPerlモジュールを作った
  • DBIの初期化を各.cgiでやっていたのでPerlモジュールに切り出した
  • よく使われていた処理もまとめてPerlモジュールに持っていった
  • 引数でテストモードを指定するとTest::mysqldに繋がるようにした
    • テストコードが一切無かったのでテストを書く布石にしたかった
単体テストを書くようにした
  • ↑の通り、テストが無かったのでTest::Moreでテストを書くようにした
    • その前に.cgiは関数化されていなかったので関数化するところから始めた
    • strictをつけると動かなくなるコードもたくさんあったので合わせて直していった
  • DB関連のテストには↑のモジュールとTest::Fixture::DBIを使った

新しい言語・フレームワークの導入

Python(Flask + SQLAlchemy)
  • Perlで各自が好き勝手にコードを書いているとメンテナンスが辛くなるというのがチームの共通認識だった
    • 当時はコードレビューをするという文化も無かったし…
  • チーム内でPythonに興味を持っている人が多かったので新規システムを作るタイミングで思い切って導入してみた
  • DjangoPyramidを使わなかった理由としては、
    • 今までがcgiオンリーだったので重量級フレームワークに慣れている人がいなかった
    • ロックインされたくなかった
    • といったところ
  • py.testでテストし、pep8pyflakesでコードのチェックをするようにした
  • 今まではテーブルの管理を一切していなかったのでalembicFlask-Migrateで管理するようにした
Go
  • ↑でPythonを導入したはいいけどほとんどがCentOS6上の2.6で動いているのでなんとかしたくなった
    • 最初は2.7や3系への移行を検討したけど、OSのデフォルトではないバージョンを使うのに反対する人が多かった
      • そうこうしているうちに2.7も終わりが見えてきてしまったし…
    • パッケージの管理が不十分でリリース後にImportErrorで落ちることが多々あった
      • pipではなく、yumを推奨しているチームもあったのでバージョン違いでうまくいかなかったりすることも…
    • テストやコードチェックを実施しない人が増えてきた
      • 理由としてはパッケージのインストールができないとかIDEが対応していないとか…
        • リリース後のトラブルは明らかに増えていたけど気にする人は少なかった
  • ということで、ある時期から新規システムを作るときはGoを使うようにしてみた
  • フレームワーク
  • 外部パッケージはgit subtreeでvendoringするようにした

ログ・監視

fluentdでログ収集とアラート検知をするようにした
  • 今まではアプリケーションコード内でアラートの処理を行なっていた
    • アラートの実装が漏れたり後回しにされることがあった
    • アラート処理自体に問題があってシステムが落ちてしまうこともあった
  • アプリケーション側は適切なログレベルでログを出力するだけにし、その後の処理は全てfluentdに任せるようにした

リポジトリ

Trac(svn)からGitHub Enterpriseに移行した
  • 積極的に移行したいという人は自分しかいなかったけど反対意見はあまり気にせず移行することにした
    • 自分にとっては複数人で開発するのにsvnだと厳しかった
    • 反対意見としては
      • Tracでも困らないとか
      • Tracでgitを使えば良いとか
      • gitを覚えたくないとか
        • こういう人にはなんとか覚えてもらうことにした
  • 移行後はPull Requestでコードレビューをする文化も少しずつだけど作っていった
drone.ioの導入
  • GitHub Enterpriseに移行したリポジトリでは以下のようなことをdrone.ioで実行するようにした
    • Lint
    • 単体テスト
      • Goは自作ツールでテストを回した
    • バイナリのビルド
    • ドキュメント(Sphinx)のビルド
    • Pull Requestの自動レビュー

デプロイ

fabricの導入
  • 当初は全てwikiなどに記載された手順書を頼りにコマンドを1つずつ打ち込んでいた
    • 設定ファイルの変更はvi /etc/my.cnfのような手順になっていることもあった
  • 最初に担当したシステムで耐えられなくなったのでfabric + shell scriptでデプロイをするようにした
    • ansibleを使わなかったのは間にPython2.5のホストがあって使えなかったから
    • chefを使わなかったのは
      • 対象ホストにインストールできないと思っていたから
      • ローカルにあるファイルを対象ホストに転送する方法がわからなかったから
chef-soloの導入
  • fabricだと共通処理も含めて毎回コピペして設定を作っていたのでBerkshelfが使いたくなった
  • 実はホストの手配をした際にchefがインストールされているということを知った
  • ファイル転送はfabricを使いつつ、ホストの設定にはchef-soloを使うようにした
自作デプロイツールの導入
  • 最初の頃に比べたらデプロイがだいぶ楽にはなったけどいくつか問題が出てきた
    • 踏み台ホストを経由するのでファイル転送に時間がかかる
    • rootになれる人しか使えないので特定の人に負荷が集中してしまうことがあった
      • 制限していたのはホストの状態を誰も把握できなくなってしまうと困るから
  • そこで対象ホストで実行するタイプのツールを新たに作成し
    • ファイル転送は対象ホストから直接gitで取得するようにした
      • 合わせてビルド済みのバイナリやDockerのイメージもダウンロードする
    • チームのメンバなら誰でも実行できるようにし、オペレーションを全自動で行うようにした
      • 開発時はアプリケーションコードだけでなく、オペレーションも含めてレビューをする
      • タグがついた最新のバージョンのみがデプロイされるようにしたので
        • 同じバージョンは1回しかデプロイされないし巻き戻ることはない
        • バージョンがわかればホストの状態も把握できる

こうしてみると改善系の活動を結構やってきたんだけど、それが偉い人にはあまり評価されなかったのは残念といえば残念。
というか2つ上の職位に要求されることが出来ていないからといって評価を下げられたのは正直根に持ってる。 あとは実際の新人に入社時の自分と同じレベルのことを求めたら何度か怒られてしまったことがあるのも今となっては良い思い出かな?

Vimでファイルを開く方法(基本編)

この記事はVim Advent Calendar 2016の4日目の記事です。

Vimでファイルを開くのに

プラグインを使っている人はたくさんいると思います。
これらのプラグインは大変便利なインターフェースを提供してくれているのですが、 依存しすぎてしまうと標準機能でファイルを開く方法を忘れてしまうかもしれません。

...さすがにそんなVimmerはいないと思いますが、ファイルを開く

をおさらいしてみましょう。

コマンドで開く

以下のコマンド*1の引数としてファイル名を指定します。

コマンド 説明
:e[dit] 現在のバッファでファイルを開く
:sp[lit] 水平分割してファイルを開く
:vs[plit] 垂直分割してファイルを開く
:tabe[dit] 新しいタブページを作成してファイルを開く

このとき、

  • <Tab>(または<CTRL-I>)でファイル名の補完
    • 動作はwildmode(:help wildmode)で変更可能
  • <CTRL-D>で入力にマッチするファイル名の一覧表示

をすることができます。

また、対象のファイル名を探すのに

  • ***などのワイルドカード(:help wildcard)
  • :p:hなどのファイル名修飾子(:help filename-modifiers)

を用いることもできます。

" <CTRL-D>で一覧を表示し、
:e */index<CTRL-D>
public/index.html  src/index.css      src/index.js

" <Tab>を押すと最初の候補が選択される
:e */index<Tab>
:e public/index.html

" もう1度<Tab>を押すと次の候補が選択される
:e public/index.html<Tab>
:e src/index.css
  • /usr/lib/golang/src/配下のreader.goを探す
:e /usr/lib/golang/src/**/reader.go<CTRL-D>
/usr/lib/golang/src/archive/tar/reader.go
/usr/lib/golang/src/archive/zip/reader.go
/usr/lib/golang/src/bytes/reader.go
/usr/lib/golang/src/compress/lzw/reader.go
/usr/lib/golang/src/compress/zlib/reader.go
/usr/lib/golang/src/debug/elf/reader.go
/usr/lib/golang/src/encoding/csv/reader.go
/usr/lib/golang/src/go/doc/reader.go
/usr/lib/golang/src/image/gif/reader.go
/usr/lib/golang/src/image/jpeg/reader.go
/usr/lib/golang/src/image/png/reader.go
/usr/lib/golang/src/mime/quotedprintable/reader.go
/usr/lib/golang/src/net/textproto/reader.go
/usr/lib/golang/src/strings/reader.go
/usr/lib/golang/src/testing/iotest/reader.go
" カレントディレクトリが/rootの状態で
:pwd
/root

" swagger-codegen/samples/server/petstore/go-api-server/main.goを開いている時
:echo expand('%:p')
/root/swagger-codegen/samples/server/petstore/go-api-server/main.go

" 最初の:hで"/main.go"、次の:hで"/go-api-server"が除去される
:e %:h:h/**/pom.xml<CTRL-D>
swagger-codegen/samples/server/petstore/java-inflector/pom.xml
swagger-codegen/samples/server/petstore/java-msf4j/pom.xml
swagger-codegen/samples/server/petstore/jaxrs/jersey1/pom.xml
swagger-codegen/samples/server/petstore/jaxrs/jersey2/pom.xml
swagger-codegen/samples/server/petstore/jaxrs-cxf/pom.xml
swagger-codegen/samples/server/petstore/jaxrs-cxf-cdi/pom.xml
swagger-codegen/samples/server/petstore/jaxrs-resteasy/default/pom.xml
swagger-codegen/samples/server/petstore/jaxrs-resteasy/joda/pom.xml
swagger-codegen/samples/server/petstore/jaxrs-spec/pom.xml
swagger-codegen/samples/server/petstore/scalatra/pom.xml
swagger-codegen/samples/server/petstore/spring-mvc/pom.xml
swagger-codegen/samples/server/petstore/spring-mvc-j8-async/pom.xml
swagger-codegen/samples/server/petstore/springboot/pom.xml
swagger-codegen/samples/server/petstore/undertow/pom.xml

キーマッピングで開く

ファイル名がある場所にカーソルを移動し、以下のキー*2を入力します。

キー 説明
gf 現在のバッファでファイルを開く
CTRL-W f 水平分割してファイルを開く
CTRL-W CTRL-F
CTRL-W gf 新しいタブページを作成してファイルを開く

現在開いているバッファにファイル名があれば良いですが、無い場合は:r!lsfindなどの外部コマンドを用いてファイル一覧を作成してしまいましょう。

" 新しいバッファにカレントディレクトリのファイル一覧を作成
:new | r! ls

なお、:newでバッファを作成した場合、デフォルトではgfでファイルを開く際にエラー(E37)になってしまいます。
その場合、

  • set hidden ... ウィンドウ内に表示されなくなる際にバッファを隠す

    • 全てのバッファが対象
    • Vim終了時に未保存バッファが残っているとエラーになる
  • set bufhidden=hide ... ウィンドウ内に表示されなくなる際にバッファを隠す

    • カレントバッファのみが対象
    • Vim終了時に当該バッファが未保存だとエラーになる
  • set buftype=nofile ... バッファを書き込まれる予定のないバッファにする

    • カレントバッファのみが対象
    • Vim終了時に当該バッファが未保存でもエラーにならない

などの設定でバッファを保存せずに切り替えられるようにしてあげる必要があります。

また、ファイル一覧に大量のファイルが表示されてしまった場合

  • /{pattern}で検索したり、
  • :g/{pattern}/dでフィルタしてあげると

目的のファイルが探しやすくなります。

:new | r! find . -type f
" Windowsの場合
:new | r! dir . /b /s /a-d
  • 現在開いているファイルがあるディレクトリ配下のファイル一覧を作成
" findの引数は実行前に<Tab>で展開しておく
:new | r! find %:p:h<Tab> -type f
" Windowsの場合
:new | r! dir %:p:h<Tab> /b /s /a-d
  • ファイル一覧を作成するユーザコマンドの定義

上記のコマンドを毎回入力するのが面倒な場合、.vimrcに以下のようなコマンドを追加しておくと便利です。

" 新しいscratchバッファ(:help special-buffers 参照)を作成する
command! -bar NewScratch new | setlocal buftype=nofile bufhidden=hide noswapfile

" :NewScratchで作成したバッファにfindコマンドの出力内容を挿入する
" FIX: <args>は""で囲まないとスペースの入ったパスが正しく処理できない(derisさん、ありがとうございます)
command! -nargs=1 -complete=dir Files NewScratch | r! find "<args>" -type f
" Windowsの場合
" FIX: <args>は""で囲まないとスペースの入ったパスが正しく処理できない(derisさん、ありがとうございます)
" command! -nargs=1 -complete=dir Files NewScratch | r! dir "<args>" /b /a-d /s

" %:p:hを引数として:Filesを実行する(<args>には%:p:hが展開された状態で渡される)
command! FilesBuffer Files %:p:h

" .を引数として:Filesを実行する
command! FilesCurrent Files .

まとめ

Vimの標準の機能でファイルを開く方法を紹介しました。

単にファイルを開くだけなら十分ですが、インタラクティブ性や非同期性が必要な場面になると物足りないところがあるかもしれません。
そういった時には組み込み関数と合わせて使ってみたり、プラグインを活用すると良いと思います。

*1:詳細は :help edit-a-file, :help opening-window, :help tab-page-commands 参照

*2:詳細は :help window-tag 参照

builderscon tokyo 2016 に行ってきた

「知らなかった、を聞く」がテーマの builderscon tokyo 2016 に行ってきました。

あのmattnさんが発表するセッションがあるということで気になっていたイベント。
チケット販売日はたまたま代休を取っていて、 たまたま販売開始のアナウンスを見たのでとりあえずポチっておいたところ、なんと販売開始から3時間で売り切れてしまったようです。
普通に出社していたらチケットが残っているうちに気づくことはなかったはずなので休日出勤をしていたのが本当にラッキーでした。

参加したセッション

  1. OSSWindows で動いてこそ楽しい(トラックA)
  2. 動け!Golang 〜圧倒的IoTツール開発へようこそ〜(トラックB)
  3. Automatic Smile Camera を作った話 - 親バカハックノススメ -(トラックB)
  4. 人工知能によってプログラムを有機化する(トラックA)
  5. Highly available and scalable Kubernetes on AWS(トラックA)
  6. CSSを破綻させない(トラックB)
  7. Docker swarm mode などで作る PaaS モドキとその悲しみ(トラックB)
  8. 世の中の困り事はだいたいGoのコード自動生成で解決する(トラックB)
  9. Bluetooth キーボードの作りかた(トラックA)

感想

最初のセッションの後、mattnさんにご挨拶することができた時点で満足度は100%。

他にも

  • mattnさんのプレゼンは内容だけでなく、テクニックにも「おおっ」となったり
    • 大鏡を使う
    • スライド上に時間、ページ数を表示する
    • デモのために予め電源オプションを設定しておく
  • 全くの専門外だけどゲームAIの進化の歴史とその裏事情!?がとても面白かったです
    • 知識や思考をどのようにしてアーキテクチャへと落とし込んでいったのか
    • ハードの制約やゲームバランスがあるので何でもやれば良いというわけではない
    • ゲーム本体の方ではなく、開発やQAにAIを適用する

また、イベント全体に関しては、

  • セッションがほぼ時間通りで進行がとてもしっかりしていた
    • 今まで参加したイベントは大体が後半になると時間が押してしまっていたので...
  • Red Bull飲み放題がヤバかった
    • 会場の制約的につい飲み過ぎてしまう...
  • プロジェクタが低かった
    • 席によっては前の人の頭でスライドがとても見づらい
  • 注意事項などを完全に見逃していた
    • ちゃんとページを見ておけば良かったんだろうけどトップページにもリンクが欲しかった

といったところ。

まあとても楽しかったので次回もすごく楽しみです。

VimConf 2016 に行ってきた

VimConf 2016に行ってきた。

発表メモ

Introduction to Vim 8.0 by Ken Takata
  • 最近Vimに入った機能の中でjob, timer, packagesは使ったけど *1 *2 Partial, lambda, closureはまだ触っていないので試してみたい
  • 日本人VimmerVim本体に多くのパッチを送っているのは知っていたけど改めて数字で見てみると予想以上にすごかった
  • Vimのテストが充実してきたおかげで新機能の使用例としても参考にできてありがたい
Vim as the MAIN text editor by bird_nitryn
  • 自分もVimに乗り換えた時は同じようにメインエディタにして使いまくった
  • 最近はVimmerを育てる機会の方が多いので参考にしたい
Denite.nvim ~The next generation of unite~ by Shougo
  • unite.vimを使っていてパフォーマンス的な不満は特になかったけどデモに触発されてMacVimでDenite.nvimを試してみたらすごく速かった
  • Decoupled UIはちょっと気になるのでそのうち試してみたい
Go、C、Pythonのためのdeoplete.nvimのソースの紹介と、Neovim専用にpure Goでvim-goをスクラッチした話 by zchee
  • neovimに全然興味なかったけど発表を聞いてとりあえずインストールしてみることにした
  • nvim-goの作りが気になるのでソースを見てみる
エディタの壁を越えるGoの開発ツールの文化と作成法 by tenntenn
  • 自分の近くでは「Goやったことある方」でほとんどの人が手を挙げていた
  • gofmt(ごーふむと)、GOOS(ぐーす)、GOARCH(ごーち)
  • ファイルを生成するツール *3 は作ったから次はファイルを書き換えるツールと思っていたのでgorenameのところがとても参考になった
vim-mode-plus for Atom editor by t9md
  • vim-mode-plusのアーキテクチャとそこに到るまでの考え方がただただすごかった
    • Vimでテキストを編集するということへの捉え方
    • モーションやオペレータの表現
  • persistence-selectionはVimにも欲しい
Vimの日本語ドキュメント by MURAOKA Taro
  • 「翻訳作業に手と目と知恵を貸してくれる人募集中」
    • リファレンス&ユーザー・マニュアル
    • メッセージ
    • メニュー
    • など
  • 脱線しかけたのはAho-Corasick法(文字列探索アルゴリズム)
  • 技術者はSPOFは排除したいはず
Vim script parser written in Go by haya14busa
  • Fixer、Formatterに期待!
  • stacktrace便利そう
  • Vim8とV8(node)は紛らわしい?
僕の友達を紹介するよ by aiya000
Best practices for building Vim plugins by thinca
  • :help design-goalsは知らなかった
  • シャイで有名なthincaさんがハイテンションで発表に懸ける強い想いが感じられた

感想

  • Vimハラスメント」に気をつけようと思った
    • (自分としてはネタのつもりだけど)職場でよく「Vimを使おう」と言っているので...
      • 開発関連のやるべき事をやってくれていれば何も言わないけどできていない
      • Vimだったらそのためにどうすれば良いかはいくらでもサポートできる
      • というのが言い訳
  • 今回はチームのメンバ(2名)に参加してもらう事に成功した
    • 楽しんでもらえたようで良かった

終わりに

発表者のみなさま、スタッフのみなさま、会場を提供してくださったミクシィさん、
ありがとうございました。
来年も是非参加したいです。

gRPCサーバのベンチマーククライアントを生成する

google.golang.org/grpcでサーバ書いたのでそろそろベンチマークしてみようと思ったらgoogle.golang.org/grpc/benchmarkという便利そうなパッケージを発見した。

早速clientをビルドしてみたけどgrpc_testingパッケージ専用だったので中のmain.goをテンプレート化して任意のパッケージで使えるようにするツールを作ってみた。
※今のところstreaming RPCには非対応

github.com

exampleshelloworldで試してみるとこんな感じ。

# ベンチマーククライアントを生成する
$ grpc-bench-generator -path $GOPATH/src/google.golang.org/grpc/examples/helloworld/helloworld > main.go

# greeter_serverが起動している状態で実行する
$ go run main.go -server=localhost:50051 -duration=1 -enable_ssl=false -data='{"Name": "grpc-bench-generator"}'
2016/09/23 15:20:57 Client profiling address:  [::]:62291
2016/09/23 15:20:58 Histogram (unit: µs)
Count: 5961  Min: 126  Max: 737  Avg: 164.21
------------------------------------------------------------
[126.000000, 127.000000)     1    0.0%    0.0%  
[127.000000, 127.025476)     0    0.0%    0.0%  
[127.025476, 127.051602)     0    0.0%    0.0%  
[127.051602, 127.078393)     0    0.0%    0.0%  
[127.078393, 127.105866)     0    0.0%    0.0%  
[127.105866, 127.134040)     0    0.0%    0.0%  
[127.134040, 127.162931)     0    0.0%    0.0%  
[127.162931, 127.192558)     0    0.0%    0.0%  
[127.192558, 127.222940)     0    0.0%    0.0%  
[127.222940, 127.254096)     0    0.0%    0.0%  
[127.254096, 127.286046)     0    0.0%    0.0%  
[127.286046, 127.318810)     0    0.0%    0.0%  
[127.318810, 127.352408)     0    0.0%    0.0%  
[127.352408, 127.386863)     0    0.0%    0.0%  
[127.386863, 127.422195)     0    0.0%    0.0%  
[127.422195, 127.458427)     0    0.0%    0.0%  
[127.458427, 127.495583)     0    0.0%    0.0%  
[127.495583, 127.533685)     0    0.0%    0.0%  
[127.533685, 127.572757)     0    0.0%    0.0%  
[127.572757, 127.612826)     0    0.0%    0.0%  
[127.612826, 127.653914)     0    0.0%    0.0%  
[127.653914, 127.696050)     0    0.0%    0.0%  
[127.696050, 127.739259)     0    0.0%    0.0%  
[127.739259, 127.783569)     0    0.0%    0.0%  
[127.783569, 127.829008)     0    0.0%    0.0%  
[127.829008, 127.875605)     0    0.0%    0.0%  
[127.875605, 127.923388)     0    0.0%    0.0%  
[127.923388, 127.972389)     0    0.0%    0.0%  
[127.972389, 128.022638)     1    0.0%    0.0%  
[128.022638, 128.074168)     0    0.0%    0.0%  
[128.074168, 128.127010)     0    0.0%    0.0%  
[128.127010, 128.181199)     0    0.0%    0.0%  
[128.181199, 128.236768)     0    0.0%    0.0%  
[128.236768, 128.293752)     0    0.0%    0.0%  
[128.293752, 128.352189)     0    0.0%    0.0%  
[128.352189, 128.412114)     0    0.0%    0.0%  
[128.412114, 128.473566)     0    0.0%    0.0%  
[128.473566, 128.536583)     0    0.0%    0.0%  
[128.536583, 128.601206)     0    0.0%    0.0%  
[128.601206, 128.667475)     0    0.0%    0.0%  
[128.667475, 128.735433)     0    0.0%    0.0%  
[128.735433, 128.805122)     0    0.0%    0.0%  
[128.805122, 128.876586)     0    0.0%    0.0%  
[128.876586, 128.949871)     0    0.0%    0.0%  
[128.949871, 129.025023)     6    0.1%    0.1%  
[129.025023, 129.102090)     0    0.0%    0.1%  
[129.102090, 129.181119)     0    0.0%    0.1%  
[129.181119, 129.262163)     0    0.0%    0.1%  
[129.262163, 129.345271)     0    0.0%    0.1%  
[129.345271, 129.430496)     0    0.0%    0.1%  
[129.430496, 129.517893)     0    0.0%    0.1%  
[129.517893, 129.607516)     0    0.0%    0.1%  
[129.607516, 129.699422)     0    0.0%    0.1%  
[129.699422, 129.793670)     0    0.0%    0.1%  
[129.793670, 129.890319)     0    0.0%    0.1%  
[129.890319, 129.989430)     0    0.0%    0.1%  
[129.989430, 130.091066)    17    0.3%    0.4%  
[130.091066, 130.195292)     0    0.0%    0.4%  
[130.195292, 130.302172)     0    0.0%    0.4%  
[130.302172, 130.411776)     0    0.0%    0.4%  
[130.411776, 130.524172)     0    0.0%    0.4%  
[130.524172, 130.639431)     0    0.0%    0.4%  
[130.639431, 130.757627)     0    0.0%    0.4%  
[130.757627, 130.878834)     0    0.0%    0.4%  
[130.878834, 131.003129)    33    0.6%    1.0%  
[131.003129, 131.130591)     0    0.0%    1.0%  
[131.130591, 131.261299)     0    0.0%    1.0%  
[131.261299, 131.395338)     0    0.0%    1.0%  
[131.395338, 131.532792)     0    0.0%    1.0%  
[131.532792, 131.673747)     0    0.0%    1.0%  
[131.673747, 131.818294)     0    0.0%    1.0%  
[131.818294, 131.966522)     0    0.0%    1.0%  
[131.966522, 132.118528)    42    0.7%    1.7%  
[132.118528, 132.274405)     0    0.0%    1.7%  
[132.274405, 132.434254)     0    0.0%    1.7%  
[132.434254, 132.598176)     0    0.0%    1.7%  
[132.598176, 132.766273)     0    0.0%    1.7%  
[132.766273, 132.938653)     0    0.0%    1.7%  
[132.938653, 133.115425)    45    0.8%    2.4%  
[133.115425, 133.296700)     0    0.0%    2.4%  
[133.296700, 133.482593)     0    0.0%    2.4%  
[133.482593, 133.673223)     0    0.0%    2.4%  
[133.673223, 133.868708)     0    0.0%    2.4%  
[133.868708, 134.069174)    61    1.0%    3.5%  
[134.069174, 134.274748)     0    0.0%    3.5%  
[134.274748, 134.485558)     0    0.0%    3.5%  
[134.485558, 134.701739)     0    0.0%    3.5%  
[134.701739, 134.923428)     0    0.0%    3.5%  
[134.923428, 135.150764)    72    1.2%    4.7%  
[135.150764, 135.383892)     0    0.0%    4.7%  
[135.383892, 135.622960)     0    0.0%    4.7%  
[135.622960, 135.868118)     0    0.0%    4.7%  
[135.868118, 136.119521)   113    1.9%    6.6%  
[136.119521, 136.377330)     0    0.0%    6.6%  
[136.377330, 136.641706)     0    0.0%    6.6%  
[136.641706, 136.912818)     0    0.0%    6.6%  
[136.912818, 137.190837)   127    2.1%    8.7%  
[137.190837, 137.475939)     0    0.0%    8.7%  
[137.475939, 137.768304)     0    0.0%    8.7%  
[137.768304, 138.068117)   165    2.8%   11.5%  
[138.068117, 138.375569)     0    0.0%   11.5%  
[138.375569, 138.690854)     0    0.0%   11.5%  
[138.690854, 139.014170)   179    3.0%   14.5%  
[139.014170, 139.345724)     0    0.0%   14.5%  
[139.345724, 139.685724)     0    0.0%   14.5%  
[139.685724, 140.034387)   193    3.2%   17.7%  
[140.034387, 140.391932)     0    0.0%   17.7%  
[140.391932, 140.758586)     0    0.0%   17.7%  
[140.758586, 141.134581)   198    3.3%   21.0%  
[141.134581, 141.520155)     0    0.0%   21.0%  
[141.520155, 141.915552)     0    0.0%   21.0%  
[141.915552, 142.321022)   193    3.2%   24.3%  
[142.321022, 142.736822)     0    0.0%   24.3%  
[142.736822, 143.163215)   181    3.0%   27.3%  
[143.163215, 143.600472)     0    0.0%   27.3%  
[143.600472, 144.048868)   190    3.2%   30.5%  
[144.048868, 144.508687)     0    0.0%   30.5%  
[144.508687, 144.980221)     0    0.0%   30.5%  
[144.980221, 145.463768)   169    2.8%   33.3%  
[145.463768, 145.959634)     0    0.0%   33.3%  
[145.959634, 146.468132)   169    2.8%   36.2%  
[146.468132, 146.989586)     0    0.0%   36.2%  
[146.989586, 147.524324)   148    2.5%   38.6%  
[147.524324, 148.072685)   150    2.5%   41.2%  
[148.072685, 148.635017)     0    0.0%   41.2%  
[148.635017, 149.211675)   161    2.7%   43.9%  
[149.211675, 149.803024)     0    0.0%   43.9%  
[149.803024, 150.409438)   141    2.4%   46.2%  
[150.409438, 151.031301)   135    2.3%   48.5%  
[151.031301, 151.669008)     0    0.0%   48.5%  
[151.669008, 152.322961)   122    2.0%   50.5%  
[152.322961, 152.993574)     0    0.0%   50.5%  
[152.993574, 153.681272)   127    2.1%   52.7%  
[153.681272, 154.386490)   120    2.0%   54.7%  
[154.386490, 155.109674)   120    2.0%   56.7%  
[155.109674, 155.851282)     0    0.0%   56.7%  
[155.851282, 156.611784)    95    1.6%   58.3%  
[156.611784, 157.391661)    87    1.5%   59.7%  
[157.391661, 158.191406)    93    1.6%   61.3%  
[158.191406, 159.011526)    66    1.1%   62.4%  
[159.011526, 159.852539)     0    0.0%   62.4%  
[159.852539, 160.714979)    69    1.2%   63.6%  
[160.714979, 161.599390)    71    1.2%   64.8%  
[161.599390, 162.506333)    63    1.1%   65.8%  
[162.506333, 163.436381)    48    0.8%   66.6%  
[163.436381, 164.390124)    68    1.1%   67.8%  
[164.390124, 165.368164)    66    1.1%   68.9%  
[165.368164, 166.371122)    47    0.8%   69.7%  
[166.371122, 167.399631)    45    0.8%   70.4%  
[167.399631, 168.454342)    47    0.8%   71.2%  
[168.454342, 169.535924)    53    0.9%   72.1%  
[169.535924, 170.645061)    45    0.8%   72.8%  
[170.645061, 171.782455)    44    0.7%   73.6%  
[171.782455, 172.948825)    36    0.6%   74.2%  
[172.948825, 174.144910)    81    1.4%   75.5%  
[174.144910, 175.371467)    29    0.5%   76.0%  
[175.371467, 176.629272)    38    0.6%   76.7%  
[176.629272, 177.919121)    27    0.5%   77.1%  
[177.919121, 179.241831)    46    0.8%   77.9%  
[179.241831, 180.598239)    27    0.5%   78.3%  
[180.598239, 181.989203)    26    0.4%   78.8%  
[181.989203, 183.415604)    64    1.1%   79.9%  
[183.415604, 184.878345)    36    0.6%   80.5%  
[184.878345, 186.378351)    49    0.8%   81.3%  
[186.378351, 187.916571)    28    0.5%   81.7%  
[187.916571, 189.493980)    47    0.8%   82.5%  
[189.493980, 191.111575)    45    0.8%   83.3%  
[191.111575, 192.770381)    20    0.3%   83.6%  
[192.770381, 194.471447)    56    0.9%   84.6%  
[194.471447, 196.215850)    45    0.8%   85.3%  
[196.215850, 198.004694)    35    0.6%   85.9%  
[198.004694, 199.839111)    17    0.3%   86.2%  
[199.839111, 201.720262)    38    0.6%   86.8%  
[201.720262, 203.649339)    33    0.6%   87.4%  
[203.649339, 205.627561)    27    0.5%   87.8%  
[205.627561, 207.656181)    30    0.5%   88.3%  
[207.656181, 209.736483)    28    0.5%   88.8%  
[209.736483, 211.869784)    30    0.5%   89.3%  
[211.869784, 214.057433)    56    0.9%   90.3%  
[214.057433, 216.300816)    28    0.5%   90.7%  
[216.300816, 218.601351)    44    0.7%   91.5%  
[218.601351, 220.960497)    21    0.4%   91.8%  
[220.960497, 223.379744)    60    1.0%   92.8%  
[223.379744, 225.860625)    31    0.5%   93.3%  
[225.860625, 228.404710)    44    0.7%   94.1%  
[228.404710, 231.013609)    51    0.9%   94.9%  
[231.013609, 233.688973)    25    0.4%   95.4%  
[233.688973, 236.432496)    46    0.8%   96.1%  
[236.432496, 239.245913)    50    0.8%   97.0%  
[239.245913, 242.131007)    34    0.6%   97.5%  
[242.131007, 245.089602)    28    0.5%   98.0%  
[245.089602, 248.123571)    19    0.3%   98.3%  
[248.123571, 251.234835)    15    0.3%   98.6%  
[251.234835, 254.425362)    18    0.3%   98.9%  
[254.425362, 257.697172)    10    0.2%   99.0%  
[257.697172, 261.052336)    12    0.2%   99.2%  
[261.052336, 264.492978)     3    0.1%   99.3%  
[264.492978, 268.021274)     4    0.1%   99.4%  
[268.021274, 271.639459)     4    0.1%   99.4%  
[271.639459, 275.349822)     2    0.0%   99.5%  
[275.349822, 279.154711)     1    0.0%   99.5%  
[279.154711, 283.056535)     2    0.0%   99.5%  
[283.056535, 287.057764)     2    0.0%   99.5%  
[287.057764, 291.160929)     3    0.1%   99.6%  
[291.160929, 295.368628)     0    0.0%   99.6%  
[295.368628, 299.683523)     1    0.0%   99.6%  
[299.683523, 304.108346)     2    0.0%   99.6%  
[304.108346, 308.645898)     0    0.0%   99.6%  
[308.645898, 313.299050)     1    0.0%   99.7%  
[313.299050, 318.070748)     0    0.0%   99.7%  
[318.070748, 322.964011)     0    0.0%   99.7%  
[322.964011, 327.981936)     0    0.0%   99.7%  
[327.981936, 333.127700)     1    0.0%   99.7%  
[333.127700, 338.404559)     0    0.0%   99.7%  
[338.404559, 343.815854)     0    0.0%   99.7%  
[343.815854, 349.365008)     0    0.0%   99.7%  
[349.365008, 355.055535)     1    0.0%   99.7%  
[355.055535, 360.891035)     1    0.0%   99.7%  
[360.891035, 366.875203)     1    0.0%   99.7%  
[366.875203, 373.011825)     2    0.0%   99.8%  
[373.011825, 379.304787)     0    0.0%   99.8%  
[379.304787, 385.758070)     1    0.0%   99.8%  
[385.758070, 392.375759)     1    0.0%   99.8%  
[392.375759, 399.162043)     2    0.0%   99.8%  
[399.162043, 406.121217)     1    0.0%   99.8%  
[406.121217, 413.257685)     1    0.0%   99.9%  
[413.257685, 420.575964)     0    0.0%   99.9%  
[420.575964, 428.080687)     0    0.0%   99.9%  
[428.080687, 435.776602)     1    0.0%   99.9%  
[435.776602, 443.668581)     0    0.0%   99.9%  
[443.668581, 451.761619)     0    0.0%   99.9%  
[451.761619, 460.060839)     1    0.0%   99.9%  
[460.060839, 468.571492)     0    0.0%   99.9%  
[468.571492, 477.298965)     1    0.0%   99.9%  
[477.298965, 486.248783)     0    0.0%   99.9%  
[486.248783, 495.426610)     0    0.0%   99.9%  
[495.426610, 504.838254)     1    0.0%   99.9%  
[504.838254, 514.489672)     2    0.0%  100.0%  
[514.489672, 524.386974)     0    0.0%  100.0%  
[524.386974, 534.536422)     0    0.0%  100.0%  
[534.536422, 544.944442)     0    0.0%  100.0%  
[544.944442, 555.617620)     0    0.0%  100.0%  
[555.617620, 566.562712)     0    0.0%  100.0%  
[566.562712, 577.786645)     1    0.0%  100.0%  
[577.786645, 589.296522)     0    0.0%  100.0%  
[589.296522, 601.099630)     0    0.0%  100.0%  
[601.099630, 613.203438)     0    0.0%  100.0%  
[613.203438, 625.615606)     0    0.0%  100.0%  
[625.615606, 638.343992)     0    0.0%  100.0%  
[638.343992, 651.396650)     0    0.0%  100.0%  
[651.396650, 664.781843)     0    0.0%  100.0%  
[664.781843, 678.508041)     0    0.0%  100.0%  
[678.508041, 692.583933)     0    0.0%  100.0%  
[692.583933, 707.018428)     0    0.0%  100.0%  
[707.018428, 721.820660)     0    0.0%  100.0%  
[721.820660, 737.000000)     0    0.0%  100.0%  
[737.000000,        inf)     1    0.0%  100.0%  

2016/09/23 15:20:58 Status Codes
OK: 5961