Add various generator improvements
[govpp.git] / examples / perf-bench / perf-bench.go
1 // Copyright (c) 2017 Cisco and/or its affiliates.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at:
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // Binary simple-client is an example VPP management application that exercises the
16 // govpp API on real-world use-cases.
17 package main
18
19 import (
20         "flag"
21         "fmt"
22         "log"
23         "time"
24
25         "github.com/pkg/profile"
26         "github.com/sirupsen/logrus"
27
28         "git.fd.io/govpp.git/adapter"
29         "git.fd.io/govpp.git/adapter/socketclient"
30         "git.fd.io/govpp.git/adapter/vppapiclient"
31         "git.fd.io/govpp.git/api"
32         "git.fd.io/govpp.git/core"
33         "git.fd.io/govpp.git/examples/binapi/vpe"
34 )
35
36 const (
37         defaultSyncRequestCount  = 1000
38         defaultAsyncRequestCount = 10000
39 )
40
41 func main() {
42         // parse optional flags
43         var sync, prof, sock bool
44         var cnt int
45         flag.BoolVar(&sync, "sync", false, "run synchronous perf test")
46         flag.BoolVar(&sock, "sock", false, "use socket client for VPP API")
47         flag.IntVar(&cnt, "count", 0, "count of requests to be sent to VPP")
48         flag.BoolVar(&prof, "prof", false, "generate profile data")
49         flag.Parse()
50
51         if cnt == 0 {
52                 // no specific count defined - use defaults
53                 if sync {
54                         cnt = defaultSyncRequestCount
55                 } else {
56                         cnt = defaultAsyncRequestCount
57                 }
58         }
59
60         if prof {
61                 defer profile.Start().Stop()
62         }
63
64         var a adapter.VppAPI
65         if sock {
66                 a = socketclient.NewVppClient("/run/vpp-api.sock")
67         } else {
68                 a = vppapiclient.NewVppClient("")
69         }
70
71         // connect to VPP
72         conn, err := core.Connect(a)
73         if err != nil {
74                 log.Fatalln("Error:", err)
75         }
76         defer conn.Disconnect()
77
78         // create an API channel
79         ch, err := conn.NewAPIChannelBuffered(cnt, cnt)
80         if err != nil {
81                 log.Fatalln("Error:", err)
82         }
83         defer ch.Close()
84
85         ch.SetReplyTimeout(time.Second * 2)
86
87         // log only errors
88         core.SetLogger(&logrus.Logger{Level: logrus.ErrorLevel})
89
90         // run the test & measure the time
91         start := time.Now()
92
93         if sync {
94                 // run synchronous test
95                 syncTest(ch, cnt)
96         } else {
97                 // run asynchronous test
98                 asyncTest(ch, cnt)
99         }
100
101         elapsed := time.Since(start)
102         fmt.Println("Test took:", elapsed)
103         fmt.Printf("Requests per second: %.0f\n", float64(cnt)/elapsed.Seconds())
104
105         time.Sleep(time.Second)
106 }
107
108 func syncTest(ch api.Channel, cnt int) {
109         fmt.Printf("Running synchronous perf test with %d requests...\n", cnt)
110
111         for i := 0; i < cnt; i++ {
112                 req := &vpe.ControlPing{}
113                 reply := &vpe.ControlPingReply{}
114
115                 if err := ch.SendRequest(req).ReceiveReply(reply); err != nil {
116                         log.Fatalln("Error in reply:", err)
117                 }
118         }
119 }
120
121 func asyncTest(ch api.Channel, cnt int) {
122         fmt.Printf("Running asynchronous perf test with %d requests...\n", cnt)
123
124         ctxChan := make(chan api.RequestCtx, cnt)
125
126         go func() {
127                 for i := 0; i < cnt; i++ {
128                         ctxChan <- ch.SendRequest(&vpe.ControlPing{})
129                 }
130                 close(ctxChan)
131                 fmt.Printf("Sending asynchronous requests finished\n")
132         }()
133
134         for ctx := range ctxChan {
135                 reply := &vpe.ControlPingReply{}
136                 if err := ctx.ReceiveReply(reply); err != nil {
137                         log.Fatalln("Error in reply:", err)
138                 }
139         }
140 }