blob: 4fc88e0758bddd4743241b3dad4fde3eaba8484b [file] [log] [blame]
Jens Geyerf4598682014-05-08 23:18:44 +02001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20package main
21
22import (
23 "flag"
24 "fmt"
25 "gen/stress"
26 "log"
27 _ "net/http/pprof"
28 "os"
29 "runtime"
30 "runtime/pprof"
31 "sync"
32 "sync/atomic"
33 "thrift"
34 "time"
35)
36
37var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file")
38var memprofile = flag.String("memprofile", "", "write memory profile to this file")
39
40var (
41 host = flag.String("host", "localhost", "Host to connect")
42 port = flag.Int64("port", 9091, "Port number to connect")
43 loop = flag.Int("loops", 50000, "The number of remote thrift calls each client makes")
44 runserver = flag.Int("server", 1, "Run the Thrift server in this process")
45 clients = flag.Int("clients", 20, "Number of client threads to create - 0 implies no clients, i.e. server only")
46 callName = flag.String("call", "echoVoid", "Service method to call, one of echoVoid, echoByte, echoI32, echoI64, echoString, echiList, echoSet, echoMap")
47 compact = flag.Bool("compact", false, "Use compact protocol instead of binary.")
48 framed = flag.Bool("framed", false, "Use framed transport instead of buffered.")
49)
50var hostPort string
51
52type callT int64
53
54const (
55 echoVoid callT = iota
56 echoByte
57 echoI32
58 echoI64
59 echoString
60 echiList
61 echoSet
62 echoMap
63)
64
65var callTMap = map[string]callT{
66 "echoVoid": echoVoid,
67 "echoByte": echoByte,
68 "echoI32": echoI32,
69 "echoI64": echoI64,
70 "echoString": echoString,
71 "echiList": echiList,
72 "echoSet": echoSet,
73 "echoMap": echoMap,
74}
75var callType callT
76
77var ready, done sync.WaitGroup
78
79var clicounter int64 = 0
80var counter int64 = 0
81
82func main() {
83 flag.Parse()
84 if *memprofile != "" {
85 runtime.MemProfileRate = 100
86 }
87 var ok bool
88 if callType, ok = callTMap[*callName]; !ok {
89 log.Fatal("Unknown service call", *callName)
90 }
91 if *cpuprofile != "" {
92 f, err := os.Create(*cpuprofile)
93 if err != nil {
94 log.Fatal(err)
95 }
96 pprof.StartCPUProfile(f)
97 defer pprof.StopCPUProfile()
98 }
99 hostPort = fmt.Sprintf("%s:%d", *host, *port)
100 var protocolFactory thrift.TProtocolFactory
101 var transportFactory thrift.TTransportFactory
102
103 if *compact {
104 protocolFactory = thrift.NewTCompactProtocolFactory()
105 } else {
106 protocolFactory = thrift.NewTBinaryProtocolFactoryDefault()
107 }
108
109 if *framed {
110 transportFactory = thrift.NewTTransportFactory()
111 transportFactory = thrift.NewTFramedTransportFactory(transportFactory)
112 } else {
113 transportFactory = thrift.NewTBufferedTransportFactory(8192)
114 }
115
116 if *runserver > 0 {
117 serverTransport, err := thrift.NewTServerSocket(hostPort)
118 if err != nil {
119 log.Fatalf("Unable to create server socket: %s", err)
120 }
121
122 processor := stress.NewServiceProcessor(&handler{})
123 server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory)
124 if *clients == 0 {
125 server.Serve()
126 } else {
127 go server.Serve()
128 }
129 }
130 //start clients
131 if *clients != 0 {
132 ready.Add(*clients + 1)
133 done.Add(*clients)
134 for i := 0; i < *clients; i++ {
135 go client(protocolFactory)
136 }
137 ready.Done()
138 ready.Wait()
139 //run!
140 startTime := time.Now()
141 //wait for completion
142 done.Wait()
143 endTime := time.Now()
144 duration := endTime.Sub(startTime)
145 log.Printf("%d calls in %v (%f calls per second)\n", clicounter, duration, float64(clicounter)/duration.Seconds())
146 }
147 if *memprofile != "" {
148 f, err := os.Create(*memprofile)
149 if err != nil {
150 log.Fatal(err)
151 }
152 pprof.WriteHeapProfile(f)
153 f.Close()
154 return
155 }
156}
157
158func client(protocolFactory thrift.TProtocolFactory) {
159 trans, err := thrift.NewTSocket(hostPort)
160 if err != nil {
161 log.Fatalf("Unable to create server socket: %s", err)
162 }
163 btrans := thrift.NewTBufferedTransport(trans, 2048)
164 client := stress.NewServiceClientFactory(btrans, protocolFactory)
165 err = trans.Open()
166 if err != nil {
167 log.Fatalf("Unable to open connection: %s", err)
168 }
169 ready.Done()
170 ready.Wait()
171 switch callType {
172 case echoVoid:
173 for i := 0; i < *loop; i++ {
174 client.EchoVoid()
175 atomic.AddInt64(&clicounter, 1)
176 }
177 case echoByte:
178 for i := 0; i < *loop; i++ {
179 client.EchoByte(42)
180 atomic.AddInt64(&clicounter, 1)
181 }
182 case echoI32:
183 for i := 0; i < *loop; i++ {
184 client.EchoI32(4242)
185 atomic.AddInt64(&clicounter, 1)
186 }
187 case echoI64:
188 for i := 0; i < *loop; i++ {
189 client.EchoI64(424242)
190 atomic.AddInt64(&clicounter, 1)
191 }
192 case echoString:
193 for i := 0; i < *loop; i++ {
194 client.EchoString("TestString")
195 atomic.AddInt64(&clicounter, 1)
196 }
197 case echiList:
198 l := []int8{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8}
199 for i := 0; i < *loop; i++ {
200 client.EchoList(l)
201 atomic.AddInt64(&clicounter, 1)
202 }
203 case echoSet:
204 s := map[int8]bool{-10: true, -9: true, -8: true, -7: true, -6: true, -5: true, -4: true, -3: true, -2: true, -1: true, 0: true, 1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true}
205 for i := 0; i < *loop; i++ {
206 client.EchoSet(s)
207 atomic.AddInt64(&clicounter, 1)
208 }
209 case echoMap:
210 m := map[int8]int8{
211 -10: 10, -9: 9, -8: 8, -7: 7, -6: 6, -5: 5, -4: 4, -3: 3, -2: 2, -1: 1, 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8}
212 for i := 0; i < *loop; i++ {
213 client.EchoMap(m)
214 atomic.AddInt64(&clicounter, 1)
215 }
216 }
217
218 done.Done()
219}
220
221type handler struct{}
222
223func (h *handler) EchoVoid() (err error) {
224 atomic.AddInt64(&counter, 1)
225 return nil
226}
227func (h *handler) EchoByte(arg int8) (r int8, err error) {
228 atomic.AddInt64(&counter, 1)
229 return arg, nil
230}
231func (h *handler) EchoI32(arg int32) (r int32, err error) {
232 atomic.AddInt64(&counter, 1)
233 return arg, nil
234}
235func (h *handler) EchoI64(arg int64) (r int64, err error) {
236 atomic.AddInt64(&counter, 1)
237 return arg, nil
238}
239func (h *handler) EchoString(arg string) (r string, err error) {
240 atomic.AddInt64(&counter, 1)
241 return arg, nil
242}
243func (h *handler) EchoList(arg []int8) (r []int8, err error) {
244 atomic.AddInt64(&counter, 1)
245 return arg, nil
246}
247func (h *handler) EchoSet(arg map[int8]bool) (r map[int8]bool, err error) {
248 atomic.AddInt64(&counter, 1)
249 return arg, nil
250}
251func (h *handler) EchoMap(arg map[int8]int8) (r map[int8]int8, err error) {
252 atomic.AddInt64(&counter, 1)
253 return arg, nil
254}