diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2015-06-23 23:27:40 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-06-25 22:24:28 +0900 |
commit | 9340fa83d1a54ef71dd0143b21638e8942a377a3 (patch) | |
tree | c811962a2210e9c747139bc04795ca70794ce058 | |
parent | d933f0a0c1a0b64ec1bf19bdc113acf8b04af7e8 (diff) |
gomrt: split parsing and sending into different goroutines
another performance improvement.
[before]
$ time gomrt -i rib.20150617.2000
gomrt -i /vagrant/rib.20150617.2000 48.98s user 149.40s system 97% cpu
3:24.30 total
[after]
$ time gomrt -i rib.20150617.2000
gomrt -i /vagrant/rib.20150617.2000 30.57s user 99.59s system 96% cpu
2:15.27 total
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
-rw-r--r-- | gomrt/main.go | 130 |
1 files changed, 70 insertions, 60 deletions
diff --git a/gomrt/main.go b/gomrt/main.go index 1e44737f..1f3e7e19 100644 --- a/gomrt/main.go +++ b/gomrt/main.go @@ -72,81 +72,91 @@ func main() { idx := 0 - stream, err := client.ModPath(context.Background()) - if err != nil { - fmt.Println("failed to modpath:", err) - os.Exit(1) - } + ch := make(chan *api.Path, 1024) - for { - buf := make([]byte, mrt.COMMON_HEADER_LEN) - _, err := file.Read(buf) - if err == io.EOF { - break - } else if err != nil { - fmt.Println("failed to read:", err) - os.Exit(1) - } - - h := &mrt.Header{} - err = h.DecodeFromBytes(buf) - if err != nil { - fmt.Println("failed to parse") - os.Exit(1) - } - - buf = make([]byte, h.Len) - _, err = file.Read(buf) - if err != nil { - fmt.Println("failed to read") - os.Exit(1) - } - - msg, err := mrt.ParseBody(h, buf) - if err != nil { - fmt.Println("failed to parse:", err) - os.Exit(1) - } + go func() { - if msg.Header.Type == mrt.TABLE_DUMPv2 { - subType := mrt.SubTypeTableDumpv2(msg.Header.SubType) - var af *api.AddressFamily - switch subType { - case mrt.PEER_INDEX_TABLE: - continue - case mrt.RIB_IPV4_UNICAST: - af = api.AF_IPV4_UC - case mrt.RIB_IPV6_UNICAST: - af = api.AF_IPV6_UC - default: - fmt.Println("unsupported subType:", subType) + for { + buf := make([]byte, mrt.COMMON_HEADER_LEN) + _, err := file.Read(buf) + if err == io.EOF { + break + } else if err != nil { + fmt.Println("failed to read:", err) os.Exit(1) } - rib := msg.Body.(*mrt.Rib) - prefix := rib.Prefix.String() - path := &api.Path{} - path.Nlri = &api.Nlri{ - Af: af, - Prefix: prefix, + + h := &mrt.Header{} + err = h.DecodeFromBytes(buf) + if err != nil { + fmt.Println("failed to parse") + os.Exit(1) } - arg := &api.ModPathArguments{ - Resource: api.Resource_GLOBAL, - Path: path, + buf = make([]byte, h.Len) + _, err = file.Read(buf) + if err != nil { + fmt.Println("failed to read") + os.Exit(1) } - err = stream.Send(arg) + msg, err := mrt.ParseBody(h, buf) if err != nil { - fmt.Println("failed to send:", err) + fmt.Println("failed to parse:", err) os.Exit(1) } + if msg.Header.Type == mrt.TABLE_DUMPv2 { + subType := mrt.SubTypeTableDumpv2(msg.Header.SubType) + var af *api.AddressFamily + switch subType { + case mrt.PEER_INDEX_TABLE: + continue + case mrt.RIB_IPV4_UNICAST: + af = api.AF_IPV4_UC + case mrt.RIB_IPV6_UNICAST: + af = api.AF_IPV6_UC + default: + fmt.Println("unsupported subType:", subType) + os.Exit(1) + } + rib := msg.Body.(*mrt.Rib) + prefix := rib.Prefix.String() + path := &api.Path{} + path.Nlri = &api.Nlri{ + Af: af, + Prefix: prefix, + } + + ch <- path + } + + idx += 1 + + if idx == globalOpts.Count { + break + } } - idx += 1 + close(ch) + }() - if idx == globalOpts.Count { - break + stream, err := client.ModPath(context.Background()) + if err != nil { + fmt.Println("failed to modpath:", err) + os.Exit(1) + } + + for path := range ch { + arg := &api.ModPathArguments{ + Resource: api.Resource_GLOBAL, + Path: path, + } + + err = stream.Send(arg) + if err != nil { + fmt.Println("failed to send:", err) + os.Exit(1) } } |