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. Souzoh confidential and proprietary 自己紹介 • Koichi Shiraishi (@zchee) •

    GitHub: zchee • Twitter: _zchee_ • Go シカカケナイ ◦ Go歴: 2年 ◦ エンジニア歴: 4ヶ月 • Mercari / Souzoh ソリューションチーム所属 3
  2. 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
  3. Souzoh confidential and proprietary A C/C++ AST index server using

    libclang written in Go github.com/zchee/clang-server 10
  4. 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
  5. Souzoh confidential and proprietary zchee/clang-server • zchee/clang-serverプロジェクトは頓挫しました orz • LLVMがC++でLangage

    Server Protocol準拠なClangDの開 発が始まったため • 今までのC/C++パーサ(YouCompleteMe・rtags)に勝つため に開発し始めたが、さすがにLLVMに勝とうとは思わない • 今日は供養しに来ました 注意 12
  6. 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
  7. Souzoh confidential and proprietary • gRPCサーバー形式(gocode的な) • クライアントはgRPCでリクエストを投げれば、補完やコードジャンプ場所が返ってく る •

    go-clangという、libclangのcgoバインディングを使った • パースしたC/C++のASTはでかすぎてメモリに乗り切らない ◦ 正確に言うと、一つのプロジェクトだけであれば乗り切るが、プロジェ クトを変える毎に再インデックスが走るのは旨くない • NoSQLのLevelDBを使ってディスクキャッシュするようにした • バイナリでDBにぶち込むために、シリアライズにflatbuffersを採用 zchee/clang-server 作った(作りかけた) 14
  8. 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
  9. 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
  10. 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
  11. 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
  12. 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
  13. 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
  14. 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
  15. Souzoh confidential and proprietary flatbuffers • dgraph-io/dgraphもflatbuffersからprotobufに移行した ◦ メンテが難しすぎるとのこと •

    gogo/protobufで匹敵するレベルの速度は出せるとのこと ◦ 自分ではベンチは取っていません 結論 29