Fix perf-bench example
[govpp.git] / examples / cmd / 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         "os"
24         "time"
25
26         "github.com/pkg/profile"
27         "github.com/sirupsen/logrus"
28
29         "git.fd.io/govpp.git"
30         "git.fd.io/govpp.git/api"
31         "git.fd.io/govpp.git/core"
32         "git.fd.io/govpp.git/examples/bin_api/vpe"
33 )
34
35 const (
36         defaultSyncRequestCount  = 1000
37         defaultAsyncRequestCount = 10000
38 )
39
40 func main() {
41         // parse optional flags
42         var sync, prof bool
43         var cnt int
44         flag.BoolVar(&sync, "sync", false, "run synchronous perf test")
45         flag.IntVar(&cnt, "count", 0, "count of requests to be sent to VPP")
46         flag.BoolVar(&prof, "prof", false, "generate profile data")
47         flag.Parse()
48
49         if cnt == 0 {
50                 // no specific count defined - use defaults
51                 if sync {
52                         cnt = defaultSyncRequestCount
53                 } else {
54                         cnt = defaultAsyncRequestCount
55                 }
56         }
57
58         if prof {
59                 defer profile.Start().Stop()
60         }
61
62         // log only errors
63         core.SetLogger(&logrus.Logger{Level: logrus.ErrorLevel})
64
65         // connect to VPP
66         conn, err := govpp.Connect("")
67         if err != nil {
68                 log.Println("Error:", err)
69                 os.Exit(1)
70         }
71         defer conn.Disconnect()
72
73         // create an API channel
74         ch, err := conn.NewAPIChannelBuffered(cnt, cnt)
75         if err != nil {
76                 log.Println("Error:", err)
77                 os.Exit(1)
78         }
79         defer ch.Close()
80
81         // run the test & measure the time
82         start := time.Now()
83
84         if sync {
85                 // run synchronous test
86                 syncTest(ch, cnt)
87         } else {
88                 // run asynchronous test
89                 asyncTest(ch, cnt)
90         }
91
92         elapsed := time.Since(start)
93         fmt.Println("Test took:", elapsed)
94         fmt.Printf("Requests per second: %.0f\n", float64(cnt)/elapsed.Seconds())
95 }
96
97 func syncTest(ch api.Channel, cnt int) {
98         fmt.Printf("Running synchronous perf test with %d requests...\n", cnt)
99
100         for i := 0; i < cnt; i++ {
101                 req := &vpe.ControlPing{}
102                 reply := &vpe.ControlPingReply{}
103
104                 err := ch.SendRequest(req).ReceiveReply(reply)
105                 if err != nil {
106                         log.Println("Error in reply:", err)
107                         os.Exit(1)
108                 }
109         }
110 }
111
112 func asyncTest(ch api.Channel, cnt int) {
113         fmt.Printf("Running asynchronous perf test with %d requests...\n", cnt)
114
115         ctxChan := make(chan api.RequestCtx, cnt)
116
117         go func() {
118                 for i := 0; i < cnt; i++ {
119                         ctxChan <- ch.SendRequest(&vpe.ControlPing{})
120                 }
121                 close(ctxChan)
122                 fmt.Printf("Sending asynchronous requests finished\n")
123         }()
124
125         for ctx := range ctxChan {
126                 reply := &vpe.ControlPingReply{}
127                 if err := ctx.ReceiveReply(reply); err != nil {
128                         log.Println("Error in reply:", err)
129                         os.Exit(1)
130                 }
131         }
132 }