Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GoでC/C++パーサーを作った時のflatbuffersの知見 - CA.go #3

zchee
November 29, 2017

GoでC/C++パーサーを作った時のflatbuffersの知見 - CA.go #3

zchee

November 29, 2017
Tweet

More Decks by zchee

Other Decks in Programming

Transcript

  1. GoでC/C++パーサーを作った時の
    flatbuffersの知見
    CA.go #3

    View Slide

  2. Souzoh confidential and proprietary
    Who?
    2

    View Slide

  3. Souzoh confidential and proprietary
    自己紹介
    ● Koichi Shiraishi (@zchee)
    ● GitHub: zchee
    ● Twitter: _zchee_
    ● Go シカカケナイ
    ○ Go歴: 2年
    ○ エンジニア歴: 4ヶ月
    ● Mercari / Souzoh ソリューションチーム所属
    3

    View Slide

  4. Souzoh confidential and proprietary
    プロジェクト / コントリビュート
    ● github.com/zchee/resume
    ○ zchee/docker-machine-driver-xhyve
    ○ zchee/nvim-go
    ○ nsf/gocode
    ○ moby/hyperkit
    ○ docker/machine
    ○ gperftools/gperftools (TC Malloc)
    ○ tmux/tmux
    ○ google/flatbuffers
    ○ etc...
    4

    View Slide

  5. Souzoh confidential and proprietary
    宣伝
    5

    View Slide

  6. Souzoh confidential and proprietary 6
    https://www.wantedly.com/projects/171425

    View Slide

  7. Souzoh confidential and proprietary
    はい
    7

    View Slide

  8. Souzoh confidential and proprietary
    GoでC/C++パーサーを作った時の
    flatbuffersの知見
    8

    View Slide

  9. Souzoh confidential and proprietary
    What is “GoでC/C++パーサー” ?
    9

    View Slide

  10. Souzoh confidential and proprietary
    A C/C++ AST index server using libclang
    written in Go
    github.com/zchee/clang-server
    10

    View Slide

  11. Souzoh confidential and proprietary
    zchee/clang-server
    ● Fast indexing of C/C++ AST database onto the NoSQL, which serialized by
    flatbuffers
    ○ Now using the leveldb key-value storage
    ○ Without C bindings using the syndtr/goleveldb, which is natively
    implemented leveldb in Go
    ● Support cross-platform and multi-architecture AST indexing
    ○ macOS, BSD and Windows
    ○ arm, arm64 m68k, mips, sparc and x86_(16|32|64)
    ● Server/Client architecture over the gRPC or msgpack-rpc
    ● Built-in compile_commands.json generator using google/kati and ninja for
    Makefile
    ○ No need make for the generating compile_commands.json
    Concept
    11

    View Slide

  12. Souzoh confidential and proprietary
    zchee/clang-server
    ● zchee/clang-serverプロジェクトは頓挫しました orz
    ● LLVMがC++でLangage Server Protocol準拠なClangDの開
    発が始まったため
    ● 今までのC/C++パーサ(YouCompleteMe・rtags)に勝つため
    に開発し始めたが、さすがにLLVMに勝とうとは思わない
    ● 今日は供養しに来ました
    注意
    12

    View Slide

  13. Souzoh confidential and proprietary
    zchee/clang-server
    ● zchee/deoplete-go はNeovim+Goのための補完プラグイン
    ● Shougo/deoplete.nvim の上に実装されていて、基本Python3でしか書
    けない
    ● zchee/deoplete-clang も実はある
    ○ LLVMが公開しているlibclang-pythonをPython3にポートしたものを
    使っている
    ○ が、ctypes のオーバーヘッドが大きく、ろくにキャッシュしてないので
    遅い
    ○ Goと同じServer/Clientアーキテクチャ形式にして、Python側もgRPC
    で通信すれば早くなるのでは!?
    なぜ作ろうとしたか
    13

    View Slide

  14. Souzoh confidential and proprietary
    ● gRPCサーバー形式(gocode的な)
    ● クライアントはgRPCでリクエストを投げれば、補完やコードジャンプ場所が返ってく

    ● go-clangという、libclangのcgoバインディングを使った
    ● パースしたC/C++のASTはでかすぎてメモリに乗り切らない
    ○ 正確に言うと、一つのプロジェクトだけであれば乗り切るが、プロジェ
    クトを変える毎に再インデックスが走るのは旨くない
    ● NoSQLのLevelDBを使ってディスクキャッシュするようにした
    ● バイナリでDBにぶち込むために、シリアライズにflatbuffersを採用
    zchee/clang-server
    作った(作りかけた)
    14

    View Slide

  15. Souzoh confidential and proprietary
    What is “flatbuffers” ?
    15

    View Slide

  16. Souzoh confidential and proprietary
    ● Access to serialized data without parsing/unpacking
    ● Memory efficiency and speed
    ● Flexible
    ● Tiny code footprint
    ● Strongly typed
    ● Convenient to use
    ● Cross platform code with no dependencies
    ● >> gRPC Support <<
    google/flatbuffers
    特徴 (Why use FlatBuffers?)
    16

    View Slide

  17. Souzoh confidential and proprietary
    要はProtocol Buffersより速いらしい
    17

    View Slide

  18. Souzoh confidential and proprietary
    flatbuffers schemaサンプル
    .
    .
    // CodeCompleteResults represents a list of vim
    complete-items dictionary.
    table CodeCompleteResults {
    Results: [CompleteItem];
    }
    // ここでgRPCを定義している
    rpc_service Clang {
    Completion(Location):CodeCompleteResults
    (streaming: "...");
    }
    namespace symbol;
    /// File represents a particular source file that
    part of a project.
    table File {
    Name: string (required, key); // -> []byte
    Flags: [string]; // -> [][]byte
    TranslationUnit: string; // -> []byte
    Symbols: [Info];
    Headers: [Header];
    Includes: [string]; // -> [][]byte
    Headers: [Header];
    }
    table Header {
    FileID: string (id: 0, required, key); // -> []byte
    Mtime: long (id: 1); // time.Time.Unix(): int64
    }
    18
    https://github.com/zchee/clang-server/blob/master/symbol/schema.fbs

    View Slide

  19. Souzoh confidential and proprietary
    flatbuffers コード生成サンプル
    https://github.com/zchee/clang-server/blob/master/internal/symbol/Header.go
    * 手抜きではありません
    19

    View Slide

  20. Souzoh confidential and proprietary
    flatbuffers schemaサンプル
    .
    .
    .
    // ここでgRPCを定義している
    rpc_service Clang {
    Completion(Location):CodeCompleteResults (streaming: "...");
    }
    20
    https://github.com/zchee/clang-server/blob/master/symbol/schema.fbs

    View Slide

  21. Souzoh confidential and proprietary
    // Completion implements symbol.ClangServer Completion interface.
    func (s *server) Completion(ctx context.Context, loc *symbol.SymbolLocation) (*flatbuffers.Builder,
    error) {
    f := string(loc.FileName())
    if s.filename != f {
    .
    .
    .
    file := symbol.GetRootAsFile(buf, 0) // デシリアライズ。`buf` はDBから取ってきた[]byte
    if cErr := s.idx.ParseTranslationUnit2(file.Name(), file.Flags(), nil,
    uint32(clang.TranslationUnit_KeepGoing), &s.tu); clang.ErrorCode(cErr) != clang.Error_Success {
    log.Fatal(cErr)
    }
    }
    codeCompleteResults := new(symbol.CodeCompleteResults)
    .
    flatbuffers Go コードサンプル
    21

    View Slide

  22. Souzoh confidential and proprietary
    flatbuffers Go コードサンプル
    .
    .
    codeCompleteResults := new(symbol.CodeCompleteResults)
    result := codeCompleteResults.Marshal(s.tu.CodeCompleteAt(f, loc.Line(), loc.Col(), nil,
    clang.DefaultCodeCompleteOptions()))
    return result, nil
    }
    22

    View Slide

  23. Souzoh confidential and proprietary
    flatbuffers Go コードサンプル
    // Serve serve clang-server server with flatbuffers gRPC custom codec.
    func (s *server) Serve() {
    l, err := net.Listen("tcp", port)
    if err != nil {
    log.Fatal(err)
    }
    grpcServer := grpc.NewServer(grpc.CustomCodec(flatbuffers.FlatbuffersCodec{}))
    symbol.RegisterClangServer(grpcServer, s)
    if err := grpcServer.Serve(l); err != nil {
    log.Fatal(err)
    }
    }
    .
    .
    23
    https://github.com/zchee/clang-server/blob/master/rpc/rpc.go

    View Slide

  24. Souzoh confidential and proprietary
    gRPCに対応している
    デシリアライズが楽
    なのは分かった。
    24

    View Slide

  25. Souzoh confidential and proprietary
    じゃあシリアライズは?
    25

    View Slide

  26. Souzoh confidential and proprietary
    flatbuffers schemaサンプル
    .
    .
    // CodeCompleteResults represents a list of vim
    complete-items dictionary.
    table CodeCompleteResults {
    Results: [CompleteItem];
    }
    // ここでgRPCを定義している
    rpc_service Clang {
    Completion(Location):CodeCompleteResults
    (streaming: "...");
    }
    namespace symbol;
    /// File represents a particular source file that
    part of a project.
    table File {
    Name: string (required, key); // -> []byte
    Flags: [string]; // -> [][]byte
    TranslationUnit: string; // -> []byte
    Symbols: [Info];
    Headers: [Header];
    Includes: [string]; // -> [][]byte
    Headers: [Header];
    }
    table Header {
    FileID: string (id: 0, required, key); // -> []byte
    Mtime: long (id: 1); // time.Time.Unix(): int64
    }
    26
    https://github.com/zchee/clang-server/blob/master/symbol/schema.fbs

    View Slide

  27. Souzoh confidential and proprietary
    flatbuffers シリアライズサンプル
    https://github.com/zchee/clang-server/blob/master/symbol/type.go#L418
    https://github.com/zchee/clang-server/blob/master/symbol/type.go#L227
    * 手抜きではありません
    27

    View Slide

  28. Souzoh confidential and proprietary
    …は?
    28

    View Slide

  29. Souzoh confidential and proprietary
    flatbuffers
    ● dgraph-io/dgraphもflatbuffersからprotobufに移行した
    ○ メンテが難しすぎるとのこと
    ● gogo/protobufで匹敵するレベルの速度は出せるとのこと
    ○ 自分ではベンチは取っていません
    結論
    29

    View Slide

  30. Souzoh confidential and proprietary
    flatbuffersは
    人類には早かったのかもしれない
    30

    View Slide

  31. Souzoh confidential and proprietary 31
    実際にバイナリ組み立てたり、
    プロジェクトでメンテナンスコストを割け
    るのであれば
    選択の余地はありそう

    View Slide

  32. Souzoh confidential and proprietary 32
    ご静聴ありがとうございました!

    View Slide