blob: 1d91b61ba45fe8bd749cb6bb8647b44d99640e18 [file] [log] [blame]
Craig Tillercb2cd262016-04-01 13:59:54 -07001# Copyright 2016, Google Inc.
2# All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are
6# met:
7#
8# * Redistributions of source code must retain the above copyright
9# notice, this list of conditions and the following disclaimer.
10# * Redistributions in binary form must reproduce the above
11# copyright notice, this list of conditions and the following disclaimer
12# in the documentation and/or other materials provided with the
13# distribution.
14# * Neither the name of Google Inc. nor the names of its
15# contributors may be used to endorse or promote products derived from
16# this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30# performance scenario configuration for various languages
31
Craig Tiller15372a32016-09-08 09:21:55 -070032import math
33
Craig Tiller0bda0b32016-03-03 12:51:53 -080034WARMUP_SECONDS=5
Jan Tattermuschde874a12016-04-18 09:21:37 -070035JAVA_WARMUP_SECONDS=15 # Java needs more warmup time for JIT to kick in.
Craig Tiller0bda0b32016-03-03 12:51:53 -080036BENCHMARK_SECONDS=30
37
Jan Tattermusch427699b2016-05-05 18:10:14 -070038SMOKETEST='smoketest'
Jan Tattermuschd27888b2016-05-19 16:11:11 -070039SCALABLE='scalable'
Craig Tiller4f2d9ae2016-07-17 14:07:18 -070040SWEEP='sweep'
Craig Tillerb6df2472016-09-13 09:41:26 -070041DEFAULT_CATEGORIES=[SCALABLE, SMOKETEST]
Jan Tattermusch427699b2016-05-05 18:10:14 -070042
Jan Tattermusch299f97f2016-04-20 18:41:55 -070043SECURE_SECARGS = {'use_test_ca': True,
44 'server_host_override': 'foo.test.google.fr'}
45
Jan Tattermusch4fec48b2016-04-12 15:12:54 -070046HISTOGRAM_PARAMS = {
47 'resolution': 0.01,
48 'max_possible': 60e9,
49}
50
Craig Tiller15372a32016-09-08 09:21:55 -070051# target number of RPCs outstanding on across all client channels in
52# non-ping-pong tests (since we can only specify per-channel numbers, the
53# actual target will be slightly higher)
54OUTSTANDING_REQUESTS={
Craig Tiller6c38c1b2016-09-13 08:34:27 -070055 'async': 6400,
Craig Tiller15372a32016-09-08 09:21:55 -070056 'sync': 1000
57}
Craig Tiller0bda0b32016-03-03 12:51:53 -080058
59# wide is the number of client channels in multi-channel tests (1 otherwise)
60WIDE=64
61
62
Jan Tattermuschd7b162f2016-05-04 15:09:26 -070063def _get_secargs(is_secure):
64 if is_secure:
65 return SECURE_SECARGS
66 else:
67 return None
68
69
Jan Tattermuscha21c7e92016-05-05 17:31:52 -070070def remove_nonproto_fields(scenario):
71 """Remove special-purpose that contains some extra info about the scenario
72 but don't belong to the ScenarioConfig protobuf message"""
73 scenario.pop('CATEGORIES', None)
Jan Tattermusch37a907e2016-05-13 13:49:43 -070074 scenario.pop('CLIENT_LANGUAGE', None)
Jan Tattermuscha21c7e92016-05-05 17:31:52 -070075 scenario.pop('SERVER_LANGUAGE', None)
Sree Kuchibhotla70d9ca42017-01-27 10:54:05 -080076 scenario.pop('EXCLUDED_POLL_ENGINES', None)
Jan Tattermuscha21c7e92016-05-05 17:31:52 -070077 return scenario
78
79
Craig Tillerc5aa7002016-09-13 09:36:09 -070080def geometric_progression(start, stop, step):
81 n = start
82 while n < stop:
83 yield int(round(n))
84 n *= step
85
86
Craig Tiller412fa2a2017-01-18 15:21:54 -080087def _payload_type(use_generic_payload, req_size, resp_size):
88 r = {}
89 sizes = {
90 'req_size': req_size,
91 'resp_size': resp_size,
92 }
93 if use_generic_payload:
94 r['bytebuf_params'] = sizes
95 else:
96 r['simple_params'] = sizes
Alexander Polcync6e333e2017-02-03 09:26:35 -080097 return r
Craig Tiller412fa2a2017-01-18 15:21:54 -080098
99
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700100def _ping_pong_scenario(name, rpc_type,
101 client_type, server_type,
102 secure=True,
103 use_generic_payload=False,
Craig Tiller412fa2a2017-01-18 15:21:54 -0800104 req_size=0,
105 resp_size=0,
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700106 unconstrained_client=None,
Jan Tattermusch37a907e2016-05-13 13:49:43 -0700107 client_language=None,
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700108 server_language=None,
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700109 async_server_threads=0,
Jan Tattermuscha21c7e92016-05-05 17:31:52 -0700110 warmup_seconds=WARMUP_SECONDS,
Craig Tillerb6df2472016-09-13 09:41:26 -0700111 categories=DEFAULT_CATEGORIES,
Craig Tillerc5aa7002016-09-13 09:36:09 -0700112 channels=None,
Craig Tiller0c80c7d2016-09-28 16:30:55 -0700113 outstanding=None,
Sree Kuchibhotla70d9ca42017-01-27 10:54:05 -0800114 resource_quota_size=None,
115 excluded_poll_engines=[]):
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700116 """Creates a basic ping pong scenario."""
117 scenario = {
118 'name': name,
119 'num_servers': 1,
120 'num_clients': 1,
121 'client_config': {
122 'client_type': client_type,
123 'security_params': _get_secargs(secure),
124 'outstanding_rpcs_per_channel': 1,
125 'client_channels': 1,
126 'async_client_threads': 1,
127 'rpc_type': rpc_type,
128 'load_params': {
129 'closed_loop': {}
130 },
131 'histogram_params': HISTOGRAM_PARAMS,
132 },
133 'server_config': {
134 'server_type': server_type,
135 'security_params': _get_secargs(secure),
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700136 'async_server_threads': async_server_threads,
137 },
138 'warmup_seconds': warmup_seconds,
139 'benchmark_seconds': BENCHMARK_SECONDS
140 }
Craig Tiller20afa3d2016-10-17 14:52:14 -0700141 if resource_quota_size:
142 scenario['server_config']['resource_quota_size'] = resource_quota_size
Jan Tattermusch28f6c012016-05-22 21:23:43 -0400143 if use_generic_payload:
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700144 if server_type != 'ASYNC_GENERIC_SERVER':
145 raise Exception('Use ASYNC_GENERIC_SERVER for generic payload.')
Alexander Polcynf797c652017-02-08 14:29:30 -0800146 scenario['server_config']['payload_config'] = _payload_type(use_generic_payload, req_size, resp_size)
147
Craig Tiller412fa2a2017-01-18 15:21:54 -0800148 scenario['client_config']['payload_config'] = _payload_type(use_generic_payload, req_size, resp_size)
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700149
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700150 if unconstrained_client:
Craig Tiller0c986752016-09-13 10:01:26 -0700151 outstanding_calls = outstanding if outstanding is not None else OUTSTANDING_REQUESTS[unconstrained_client]
Craig Tillerfaa835c2017-01-18 15:28:44 -0800152 # clamp buffer usage to something reasonable (16 gig for now)
153 MAX_MEMORY_USE = 16 * 1024 * 1024 * 1024
154 if outstanding_calls * max(req_size, resp_size) > MAX_MEMORY_USE:
155 outstanding_calls = max(1, MAX_MEMORY_USE / max(req_size, resp_size))
Craig Tiller15372a32016-09-08 09:21:55 -0700156 wide = channels if channels is not None else WIDE
Craig Tiller0c986752016-09-13 10:01:26 -0700157 deep = int(math.ceil(1.0 * outstanding_calls / wide))
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700158
Jan Tattermusch28f6c012016-05-22 21:23:43 -0400159 scenario['num_clients'] = 0 # use as many client as available.
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700160 scenario['client_config']['outstanding_rpcs_per_channel'] = deep
161 scenario['client_config']['client_channels'] = wide
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700162 scenario['client_config']['async_client_threads'] = 0
163 else:
164 scenario['client_config']['outstanding_rpcs_per_channel'] = 1
165 scenario['client_config']['client_channels'] = 1
166 scenario['client_config']['async_client_threads'] = 1
167
Jan Tattermusch37a907e2016-05-13 13:49:43 -0700168 if client_language:
169 # the CLIENT_LANGUAGE field is recognized by run_performance_tests.py
170 scenario['CLIENT_LANGUAGE'] = client_language
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700171 if server_language:
172 # the SERVER_LANGUAGE field is recognized by run_performance_tests.py
173 scenario['SERVER_LANGUAGE'] = server_language
Jan Tattermuscha21c7e92016-05-05 17:31:52 -0700174 if categories:
175 scenario['CATEGORIES'] = categories
Sree Kuchibhotla70d9ca42017-01-27 10:54:05 -0800176 if len(excluded_poll_engines):
177 # The polling engines for which this scenario is excluded
178 scenario['EXCLUDED_POLL_ENGINES'] = excluded_poll_engines
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700179 return scenario
180
181
Craig Tillercb2cd262016-04-01 13:59:54 -0700182class CXXLanguage:
183
184 def __init__(self):
185 self.safename = 'cxx'
186
187 def worker_cmdline(self):
188 return ['bins/opt/qps_worker']
189
190 def worker_port_offset(self):
191 return 0
192
193 def scenarios(self):
Craig Tiller0bda0b32016-03-03 12:51:53 -0800194 # TODO(ctiller): add 70% load latency test
195 for secure in [True, False]:
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700196 secstr = 'secure' if secure else 'insecure'
Craig Tiller677966a2016-09-26 07:37:28 -0700197 smoketest_categories = ([SMOKETEST] if secure else []) + [SCALABLE]
Craig Tiller0bda0b32016-03-03 12:51:53 -0800198
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700199 yield _ping_pong_scenario(
Craig Tiller4f2d9ae2016-07-17 14:07:18 -0700200 'cpp_generic_async_streaming_ping_pong_%s' % secstr,
201 rpc_type='STREAMING',
202 client_type='ASYNC_CLIENT',
203 server_type='ASYNC_GENERIC_SERVER',
Alexander Polcyna6e796f2017-01-11 13:49:43 -0800204 use_generic_payload=True, async_server_threads=1,
Jan Tattermusch427699b2016-05-05 18:10:14 -0700205 secure=secure,
206 categories=smoketest_categories)
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700207
208 yield _ping_pong_scenario(
Craig Tiller4f2d9ae2016-07-17 14:07:18 -0700209 'cpp_generic_async_streaming_qps_unconstrained_%s' % secstr,
210 rpc_type='STREAMING',
211 client_type='ASYNC_CLIENT',
212 server_type='ASYNC_GENERIC_SERVER',
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700213 unconstrained_client='async', use_generic_payload=True,
Jan Tattermusch427699b2016-05-05 18:10:14 -0700214 secure=secure,
Jan Tattermuschd27888b2016-05-19 16:11:11 -0700215 categories=smoketest_categories+[SCALABLE])
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700216
217 yield _ping_pong_scenario(
Craig Tiller4f2d9ae2016-07-17 14:07:18 -0700218 'cpp_generic_async_streaming_qps_one_server_core_%s' % secstr,
219 rpc_type='STREAMING',
220 client_type='ASYNC_CLIENT',
221 server_type='ASYNC_GENERIC_SERVER',
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700222 unconstrained_client='async', use_generic_payload=True,
Alexander Polcyna6e796f2017-01-11 13:49:43 -0800223 async_server_threads=1,
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700224 secure=secure)
Craig Tillercb2cd262016-04-01 13:59:54 -0700225
Sree Kuchibhotla923d6412016-09-26 19:32:17 -0700226 yield _ping_pong_scenario(
227 'cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_%s' %
228 (secstr),
229 rpc_type='UNARY',
230 client_type='ASYNC_CLIENT',
231 server_type='SYNC_SERVER',
232 unconstrained_client='async',
233 secure=secure,
Sree Kuchibhotla70d9ca42017-01-27 10:54:05 -0800234 categories=smoketest_categories + [SCALABLE],
235 excluded_poll_engines = ['poll-cv'])
Sree Kuchibhotla923d6412016-09-26 19:32:17 -0700236
Sree Kuchibhotlaa83ee602016-10-25 11:54:52 -0700237 yield _ping_pong_scenario(
238 'cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_%s' % secstr,
239 rpc_type='STREAMING',
240 client_type='ASYNC_CLIENT',
241 server_type='SYNC_SERVER',
242 unconstrained_client='async',
243 secure=secure,
Sree Kuchibhotla70d9ca42017-01-27 10:54:05 -0800244 categories=smoketest_categories+[SCALABLE],
245 excluded_poll_engines = ['poll-cv'])
Sree Kuchibhotlaa83ee602016-10-25 11:54:52 -0700246
Craig Tiller601cff42016-09-19 07:30:45 -0700247 for rpc_type in ['unary', 'streaming']:
248 for synchronicity in ['sync', 'async']:
249 yield _ping_pong_scenario(
250 'cpp_protobuf_%s_%s_ping_pong_%s' % (synchronicity, rpc_type, secstr),
251 rpc_type=rpc_type.upper(),
252 client_type='%s_CLIENT' % synchronicity.upper(),
253 server_type='%s_SERVER' % synchronicity.upper(),
Alexander Polcyna6e796f2017-01-11 13:49:43 -0800254 async_server_threads=1,
Craig Tiller601cff42016-09-19 07:30:45 -0700255 secure=secure)
Craig Tiller4f2d9ae2016-07-17 14:07:18 -0700256
Craig Tillerfaa835c2017-01-18 15:28:44 -0800257 for size in geometric_progression(1, 1024*1024*1024+1, 8):
258 yield _ping_pong_scenario(
259 'cpp_protobuf_%s_%s_qps_unconstrained_%s_%db' % (synchronicity, rpc_type, secstr, size),
260 rpc_type=rpc_type.upper(),
261 req_size=size,
262 resp_size=size,
263 client_type='%s_CLIENT' % synchronicity.upper(),
264 server_type='%s_SERVER' % synchronicity.upper(),
265 unconstrained_client=synchronicity,
266 secure=secure,
267 categories=[SWEEP])
268
Craig Tiller601cff42016-09-19 07:30:45 -0700269 yield _ping_pong_scenario(
270 'cpp_protobuf_%s_%s_qps_unconstrained_%s' % (synchronicity, rpc_type, secstr),
271 rpc_type=rpc_type.upper(),
272 client_type='%s_CLIENT' % synchronicity.upper(),
273 server_type='%s_SERVER' % synchronicity.upper(),
274 unconstrained_client=synchronicity,
275 secure=secure,
276 categories=smoketest_categories+[SCALABLE])
Craig Tiller4f2d9ae2016-07-17 14:07:18 -0700277
Vijay Paia582def2017-03-09 05:47:46 -0800278 # TODO(vjpai): Re-enable this test. It has a lot of timeouts
279 # and hasn't yet been conclusively identified as a test failure
280 # or race in the library
281 # yield _ping_pong_scenario(
282 # 'cpp_protobuf_%s_%s_qps_unconstrained_%s_500kib_resource_quota' % (synchronicity, rpc_type, secstr),
283 # rpc_type=rpc_type.upper(),
284 # client_type='%s_CLIENT' % synchronicity.upper(),
285 # server_type='%s_SERVER' % synchronicity.upper(),
286 # unconstrained_client=synchronicity,
287 # secure=secure,
288 # categories=smoketest_categories+[SCALABLE],
289 # resource_quota_size=500*1024)
Craig Tiller0c80c7d2016-09-28 16:30:55 -0700290
Craig Tiller601cff42016-09-19 07:30:45 -0700291 for channels in geometric_progression(1, 20000, math.sqrt(10)):
292 for outstanding in geometric_progression(1, 200000, math.sqrt(10)):
293 if synchronicity == 'sync' and outstanding > 1200: continue
294 if outstanding < channels: continue
295 yield _ping_pong_scenario(
296 'cpp_protobuf_%s_%s_qps_unconstrained_%s_%d_channels_%d_outstanding' % (synchronicity, rpc_type, secstr, channels, outstanding),
297 rpc_type=rpc_type.upper(),
298 client_type='%s_CLIENT' % synchronicity.upper(),
299 server_type='%s_SERVER' % synchronicity.upper(),
300 unconstrained_client=synchronicity, secure=secure,
301 categories=[SWEEP], channels=channels, outstanding=outstanding)
Craig Tiller4f2d9ae2016-07-17 14:07:18 -0700302
Craig Tillercb2cd262016-04-01 13:59:54 -0700303 def __str__(self):
304 return 'c++'
305
306
307class CSharpLanguage:
308
309 def __init__(self):
310 self.safename = str(self)
311
312 def worker_cmdline(self):
313 return ['tools/run_tests/performance/run_worker_csharp.sh']
314
315 def worker_port_offset(self):
316 return 100
317
318 def scenarios(self):
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700319 yield _ping_pong_scenario(
320 'csharp_generic_async_streaming_ping_pong', rpc_type='STREAMING',
321 client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER',
Jan Tattermusch427699b2016-05-05 18:10:14 -0700322 use_generic_payload=True,
Craig Tiller677966a2016-09-26 07:37:28 -0700323 categories=[SMOKETEST, SCALABLE])
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700324
325 yield _ping_pong_scenario(
326 'csharp_protobuf_async_streaming_ping_pong', rpc_type='STREAMING',
327 client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER')
328
329 yield _ping_pong_scenario(
330 'csharp_protobuf_async_unary_ping_pong', rpc_type='UNARY',
Jan Tattermusch427699b2016-05-05 18:10:14 -0700331 client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
Craig Tiller677966a2016-09-26 07:37:28 -0700332 categories=[SMOKETEST, SCALABLE])
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700333
334 yield _ping_pong_scenario(
335 'csharp_protobuf_sync_to_async_unary_ping_pong', rpc_type='UNARY',
336 client_type='SYNC_CLIENT', server_type='ASYNC_SERVER')
337
Jan Tattermusch16713b92016-05-09 14:34:11 -0700338 yield _ping_pong_scenario(
339 'csharp_protobuf_async_unary_qps_unconstrained', rpc_type='UNARY',
340 client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700341 unconstrained_client='async',
Jan Tattermuschd27888b2016-05-19 16:11:11 -0700342 categories=[SMOKETEST,SCALABLE])
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700343
Jan Tattermusch16713b92016-05-09 14:34:11 -0700344 yield _ping_pong_scenario(
345 'csharp_protobuf_async_streaming_qps_unconstrained', rpc_type='STREAMING',
346 client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
Jan Tattermuschd27888b2016-05-19 16:11:11 -0700347 unconstrained_client='async',
348 categories=[SCALABLE])
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700349
Jan Tattermuschabd1b382016-05-08 18:47:40 -0700350 yield _ping_pong_scenario(
351 'csharp_to_cpp_protobuf_sync_unary_ping_pong', rpc_type='UNARY',
352 client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
Alexander Polcyna6e796f2017-01-11 13:49:43 -0800353 server_language='c++', async_server_threads=1,
Craig Tiller677966a2016-09-26 07:37:28 -0700354 categories=[SMOKETEST, SCALABLE])
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700355
356 yield _ping_pong_scenario(
357 'csharp_to_cpp_protobuf_async_streaming_ping_pong', rpc_type='STREAMING',
358 client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
Alexander Polcyna6e796f2017-01-11 13:49:43 -0800359 server_language='c++', async_server_threads=1)
Craig Tillercb2cd262016-04-01 13:59:54 -0700360
Jan Tattermusch37a907e2016-05-13 13:49:43 -0700361 yield _ping_pong_scenario(
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700362 'csharp_to_cpp_protobuf_async_unary_qps_unconstrained', rpc_type='UNARY',
363 client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
Jan Tattermuschd27888b2016-05-19 16:11:11 -0700364 unconstrained_client='async', server_language='c++',
365 categories=[SCALABLE])
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700366
367 yield _ping_pong_scenario(
368 'csharp_to_cpp_protobuf_sync_to_async_unary_qps_unconstrained', rpc_type='UNARY',
369 client_type='SYNC_CLIENT', server_type='ASYNC_SERVER',
Jan Tattermuschd27888b2016-05-19 16:11:11 -0700370 unconstrained_client='sync', server_language='c++',
371 categories=[SCALABLE])
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700372
373 yield _ping_pong_scenario(
Jan Tattermusch37a907e2016-05-13 13:49:43 -0700374 'cpp_to_csharp_protobuf_async_unary_qps_unconstrained', rpc_type='UNARY',
375 client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
Jan Tattermuschd27888b2016-05-19 16:11:11 -0700376 unconstrained_client='async', client_language='c++',
377 categories=[SCALABLE])
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700378
Jan Tattermusch37a907e2016-05-13 13:49:43 -0700379
Craig Tillercb2cd262016-04-01 13:59:54 -0700380 def __str__(self):
381 return 'csharp'
382
383
384class NodeLanguage:
385
386 def __init__(self):
387 pass
388 self.safename = str(self)
389
390 def worker_cmdline(self):
murgatroid99b53e5d12016-10-18 09:55:28 -0700391 return ['tools/run_tests/performance/run_worker_node.sh',
392 '--benchmark_impl=grpc']
Craig Tillercb2cd262016-04-01 13:59:54 -0700393
394 def worker_port_offset(self):
395 return 200
396
397 def scenarios(self):
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700398 # TODO(jtattermusch): make this scenario work
399 #yield _ping_pong_scenario(
400 # 'node_generic_async_streaming_ping_pong', rpc_type='STREAMING',
401 # client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER',
402 # use_generic_payload=True)
403
404 # TODO(jtattermusch): make this scenario work
405 #yield _ping_pong_scenario(
406 # 'node_protobuf_async_streaming_ping_pong', rpc_type='STREAMING',
407 # client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER')
408
409 yield _ping_pong_scenario(
410 'node_protobuf_unary_ping_pong', rpc_type='UNARY',
Jan Tattermusch427699b2016-05-05 18:10:14 -0700411 client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
Craig Tiller677966a2016-09-26 07:37:28 -0700412 categories=[SCALABLE, SMOKETEST])
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700413
414 yield _ping_pong_scenario(
murgatroid999030c812016-09-16 13:25:08 -0700415 'cpp_to_node_unary_ping_pong', rpc_type='UNARY',
416 client_type='ASYNC_CLIENT', server_type='async_server',
417 client_language='c++')
418
murgatroid99faaa8b82017-03-02 10:50:34 -0800419 # TODO(murgatroid99): fix bugs with this scenario and re-enable it
420 # yield _ping_pong_scenario(
421 # 'node_protobuf_async_unary_qps_unconstrained', rpc_type='UNARY',
422 # client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
423 # unconstrained_client='async',
424 # categories=[SCALABLE, SMOKETEST])
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700425
426 # TODO(jtattermusch): make this scenario work
427 #yield _ping_pong_scenario(
428 # 'node_protobuf_async_streaming_qps_unconstrained', rpc_type='STREAMING',
429 # client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700430 # unconstrained_client='async')
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700431
432 # TODO(jtattermusch): make this scenario work
433 #yield _ping_pong_scenario(
434 # 'node_to_cpp_protobuf_async_unary_ping_pong', rpc_type='UNARY',
435 # client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
Alexander Polcyna6e796f2017-01-11 13:49:43 -0800436 # server_language='c++', async_server_threads=1)
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700437
438 # TODO(jtattermusch): make this scenario work
439 #yield _ping_pong_scenario(
440 # 'node_to_cpp_protobuf_async_streaming_ping_pong', rpc_type='STREAMING',
441 # client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
Alexander Polcyna6e796f2017-01-11 13:49:43 -0800442 # server_language='c++', async_server_threads=1)
Craig Tillercb2cd262016-04-01 13:59:54 -0700443
444 def __str__(self):
445 return 'node'
446
Ken Payson0482c102016-04-19 12:08:34 -0700447class PythonLanguage:
448
449 def __init__(self):
450 self.safename = 'python'
451
452 def worker_cmdline(self):
453 return ['tools/run_tests/performance/run_worker_python.sh']
454
455 def worker_port_offset(self):
456 return 500
457
458 def scenarios(self):
Ken Payson45c0f2b2016-07-06 19:26:09 -0700459 yield _ping_pong_scenario(
460 'python_generic_sync_streaming_ping_pong', rpc_type='STREAMING',
461 client_type='SYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER',
462 use_generic_payload=True,
Craig Tiller677966a2016-09-26 07:37:28 -0700463 categories=[SMOKETEST, SCALABLE])
Ken Payson1eb8d542016-05-10 16:57:14 -0700464
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700465 yield _ping_pong_scenario(
Ken Payson571c12e2016-06-06 23:13:27 -0700466 'python_protobuf_sync_streaming_ping_pong', rpc_type='STREAMING',
Ken Payson45c0f2b2016-07-06 19:26:09 -0700467 client_type='SYNC_CLIENT', server_type='ASYNC_SERVER')
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700468
Ken Payson1eb8d542016-05-10 16:57:14 -0700469 yield _ping_pong_scenario(
470 'python_protobuf_async_unary_ping_pong', rpc_type='UNARY',
Ken Payson45c0f2b2016-07-06 19:26:09 -0700471 client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER')
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700472
473 yield _ping_pong_scenario(
474 'python_protobuf_sync_unary_ping_pong', rpc_type='UNARY',
Ken Payson45c0f2b2016-07-06 19:26:09 -0700475 client_type='SYNC_CLIENT', server_type='ASYNC_SERVER',
Craig Tiller677966a2016-09-26 07:37:28 -0700476 categories=[SMOKETEST, SCALABLE])
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700477
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700478 yield _ping_pong_scenario(
479 'python_protobuf_sync_unary_qps_unconstrained', rpc_type='UNARY',
Ken Payson45c0f2b2016-07-06 19:26:09 -0700480 client_type='SYNC_CLIENT', server_type='ASYNC_SERVER',
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700481 unconstrained_client='sync')
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700482
Ken Payson1eb8d542016-05-10 16:57:14 -0700483 yield _ping_pong_scenario(
Ken Payson571c12e2016-06-06 23:13:27 -0700484 'python_protobuf_sync_streaming_qps_unconstrained', rpc_type='STREAMING',
Ken Payson45c0f2b2016-07-06 19:26:09 -0700485 client_type='SYNC_CLIENT', server_type='ASYNC_SERVER',
Ken Payson9a36e6c2016-06-07 17:49:03 -0700486 unconstrained_client='sync')
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700487
488 yield _ping_pong_scenario(
489 'python_to_cpp_protobuf_sync_unary_ping_pong', rpc_type='UNARY',
Ken Payson45c0f2b2016-07-06 19:26:09 -0700490 client_type='SYNC_CLIENT', server_type='ASYNC_SERVER',
Alexander Polcyna6e796f2017-01-11 13:49:43 -0800491 server_language='c++', async_server_threads=1,
Craig Tiller677966a2016-09-26 07:37:28 -0700492 categories=[SMOKETEST, SCALABLE])
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700493
Ken Payson1eb8d542016-05-10 16:57:14 -0700494 yield _ping_pong_scenario(
495 'python_to_cpp_protobuf_sync_streaming_ping_pong', rpc_type='STREAMING',
Ken Payson45c0f2b2016-07-06 19:26:09 -0700496 client_type='SYNC_CLIENT', server_type='ASYNC_SERVER',
Alexander Polcyna6e796f2017-01-11 13:49:43 -0800497 server_language='c++', async_server_threads=1)
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700498
Ken Payson0482c102016-04-19 12:08:34 -0700499 def __str__(self):
500 return 'python'
Craig Tillercb2cd262016-04-01 13:59:54 -0700501
Jan Tattermuscha5780e12016-04-15 16:14:42 -0700502class RubyLanguage:
503
504 def __init__(self):
505 pass
506 self.safename = str(self)
507
508 def worker_cmdline(self):
509 return ['tools/run_tests/performance/run_worker_ruby.sh']
510
511 def worker_port_offset(self):
512 return 300
513
514 def scenarios(self):
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700515 yield _ping_pong_scenario(
516 'ruby_protobuf_sync_streaming_ping_pong', rpc_type='STREAMING',
Jan Tattermusch427699b2016-05-05 18:10:14 -0700517 client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
Craig Tiller677966a2016-09-26 07:37:28 -0700518 categories=[SMOKETEST, SCALABLE])
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700519
520 yield _ping_pong_scenario(
521 'ruby_protobuf_unary_ping_pong', rpc_type='UNARY',
Jan Tattermusch427699b2016-05-05 18:10:14 -0700522 client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
Craig Tiller677966a2016-09-26 07:37:28 -0700523 categories=[SMOKETEST, SCALABLE])
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700524
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700525 yield _ping_pong_scenario(
526 'ruby_protobuf_sync_unary_qps_unconstrained', rpc_type='UNARY',
527 client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
528 unconstrained_client='sync')
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700529
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700530 yield _ping_pong_scenario(
531 'ruby_protobuf_sync_streaming_qps_unconstrained', rpc_type='STREAMING',
532 client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
533 unconstrained_client='sync')
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700534
535 yield _ping_pong_scenario(
536 'ruby_to_cpp_protobuf_sync_unary_ping_pong', rpc_type='UNARY',
537 client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
Alexander Polcyna6e796f2017-01-11 13:49:43 -0800538 server_language='c++', async_server_threads=1)
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700539
540 yield _ping_pong_scenario(
541 'ruby_to_cpp_protobuf_sync_streaming_ping_pong', rpc_type='STREAMING',
542 client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
Alexander Polcyna6e796f2017-01-11 13:49:43 -0800543 server_language='c++', async_server_threads=1)
Jan Tattermuscha5780e12016-04-15 16:14:42 -0700544
545 def __str__(self):
546 return 'ruby'
547
548
Jan Tattermuschde874a12016-04-18 09:21:37 -0700549class JavaLanguage:
550
551 def __init__(self):
552 pass
553 self.safename = str(self)
554
555 def worker_cmdline(self):
556 return ['tools/run_tests/performance/run_worker_java.sh']
557
558 def worker_port_offset(self):
559 return 400
560
561 def scenarios(self):
Jan Tattermusche222c002016-04-20 18:55:24 -0700562 for secure in [True, False]:
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700563 secstr = 'secure' if secure else 'insecure'
Craig Tiller677966a2016-09-26 07:37:28 -0700564 smoketest_categories = ([SMOKETEST] if secure else []) + [SCALABLE]
Jan Tattermusche222c002016-04-20 18:55:24 -0700565
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700566 yield _ping_pong_scenario(
567 'java_generic_async_streaming_ping_pong_%s' % secstr, rpc_type='STREAMING',
568 client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER',
569 use_generic_payload=True, async_server_threads=1,
Jan Tattermusch427699b2016-05-05 18:10:14 -0700570 secure=secure, warmup_seconds=JAVA_WARMUP_SECONDS,
571 categories=smoketest_categories)
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700572
573 yield _ping_pong_scenario(
574 'java_protobuf_async_streaming_ping_pong_%s' % secstr, rpc_type='STREAMING',
575 client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
576 async_server_threads=1,
577 secure=secure, warmup_seconds=JAVA_WARMUP_SECONDS)
578
579 yield _ping_pong_scenario(
580 'java_protobuf_async_unary_ping_pong_%s' % secstr, rpc_type='UNARY',
581 client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
582 async_server_threads=1,
Jan Tattermusch427699b2016-05-05 18:10:14 -0700583 secure=secure, warmup_seconds=JAVA_WARMUP_SECONDS,
584 categories=smoketest_categories)
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700585
586 yield _ping_pong_scenario(
587 'java_protobuf_unary_ping_pong_%s' % secstr, rpc_type='UNARY',
588 client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
589 async_server_threads=1,
590 secure=secure, warmup_seconds=JAVA_WARMUP_SECONDS)
591
592 yield _ping_pong_scenario(
593 'java_protobuf_async_unary_qps_unconstrained_%s' % secstr, rpc_type='UNARY',
594 client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700595 unconstrained_client='async',
Jan Tattermusch427699b2016-05-05 18:10:14 -0700596 secure=secure, warmup_seconds=JAVA_WARMUP_SECONDS,
Jan Tattermuschd27888b2016-05-19 16:11:11 -0700597 categories=smoketest_categories+[SCALABLE])
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700598
599 yield _ping_pong_scenario(
600 'java_protobuf_async_streaming_qps_unconstrained_%s' % secstr, rpc_type='STREAMING',
601 client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700602 unconstrained_client='async',
Jan Tattermuschd27888b2016-05-19 16:11:11 -0700603 secure=secure, warmup_seconds=JAVA_WARMUP_SECONDS,
604 categories=[SCALABLE])
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700605
606 yield _ping_pong_scenario(
607 'java_generic_async_streaming_qps_unconstrained_%s' % secstr, rpc_type='STREAMING',
608 client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER',
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700609 unconstrained_client='async', use_generic_payload=True,
Jan Tattermuschd27888b2016-05-19 16:11:11 -0700610 secure=secure, warmup_seconds=JAVA_WARMUP_SECONDS,
611 categories=[SCALABLE])
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700612
613 yield _ping_pong_scenario(
614 'java_generic_async_streaming_qps_one_server_core_%s' % secstr, rpc_type='STREAMING',
615 client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER',
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700616 unconstrained_client='async', use_generic_payload=True,
Jan Tattermuschd7b162f2016-05-04 15:09:26 -0700617 async_server_threads=1,
618 secure=secure, warmup_seconds=JAVA_WARMUP_SECONDS)
619
Craig Tiller4f2d9ae2016-07-17 14:07:18 -0700620 # TODO(jtattermusch): add scenarios java vs C++
Jan Tattermuschde874a12016-04-18 09:21:37 -0700621
622 def __str__(self):
623 return 'java'
624
625
Jan Tattermusch3b59b0f2016-05-10 14:44:05 -0700626class GoLanguage:
627
628 def __init__(self):
629 pass
630 self.safename = str(self)
631
632 def worker_cmdline(self):
633 return ['tools/run_tests/performance/run_worker_go.sh']
634
635 def worker_port_offset(self):
636 return 600
637
638 def scenarios(self):
639 for secure in [True, False]:
640 secstr = 'secure' if secure else 'insecure'
Craig Tiller677966a2016-09-26 07:37:28 -0700641 smoketest_categories = ([SMOKETEST] if secure else []) + [SCALABLE]
Jan Tattermusch3b59b0f2016-05-10 14:44:05 -0700642
Jan Tattermusch4bd3a7c2016-05-11 09:29:08 -0700643 # ASYNC_GENERIC_SERVER for Go actually uses a sync streaming server,
Craig Tiller4f2d9ae2016-07-17 14:07:18 -0700644 # but that's mostly because of lack of better name of the enum value.
Jan Tattermusch3b59b0f2016-05-10 14:44:05 -0700645 yield _ping_pong_scenario(
Jan Tattermusch4bd3a7c2016-05-11 09:29:08 -0700646 'go_generic_sync_streaming_ping_pong_%s' % secstr, rpc_type='STREAMING',
647 client_type='SYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER',
Jan Tattermusch3b59b0f2016-05-10 14:44:05 -0700648 use_generic_payload=True, async_server_threads=1,
649 secure=secure,
650 categories=smoketest_categories)
651
652 yield _ping_pong_scenario(
Jan Tattermusch4bd3a7c2016-05-11 09:29:08 -0700653 'go_protobuf_sync_streaming_ping_pong_%s' % secstr, rpc_type='STREAMING',
Jan Tattermusch3b59b0f2016-05-10 14:44:05 -0700654 client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
655 async_server_threads=1,
656 secure=secure)
657
658 yield _ping_pong_scenario(
Jan Tattermusch4bd3a7c2016-05-11 09:29:08 -0700659 'go_protobuf_sync_unary_ping_pong_%s' % secstr, rpc_type='UNARY',
660 client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
661 async_server_threads=1,
662 secure=secure,
663 categories=smoketest_categories)
664
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700665 # unconstrained_client='async' is intended (client uses goroutines)
Jan Tattermusch4bd3a7c2016-05-11 09:29:08 -0700666 yield _ping_pong_scenario(
667 'go_protobuf_sync_unary_qps_unconstrained_%s' % secstr, rpc_type='UNARY',
668 client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700669 unconstrained_client='async',
Jan Tattermusch3b59b0f2016-05-10 14:44:05 -0700670 secure=secure,
Jan Tattermuschd27888b2016-05-19 16:11:11 -0700671 categories=smoketest_categories+[SCALABLE])
Jan Tattermusch3b59b0f2016-05-10 14:44:05 -0700672
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700673 # unconstrained_client='async' is intended (client uses goroutines)
Jan Tattermusch3b59b0f2016-05-10 14:44:05 -0700674 yield _ping_pong_scenario(
Jan Tattermusch4bd3a7c2016-05-11 09:29:08 -0700675 'go_protobuf_sync_streaming_qps_unconstrained_%s' % secstr, rpc_type='STREAMING',
676 client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700677 unconstrained_client='async',
Jan Tattermuschd27888b2016-05-19 16:11:11 -0700678 secure=secure,
679 categories=[SCALABLE])
Jan Tattermusch3b59b0f2016-05-10 14:44:05 -0700680
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700681 # unconstrained_client='async' is intended (client uses goroutines)
Jan Tattermusch4bd3a7c2016-05-11 09:29:08 -0700682 # ASYNC_GENERIC_SERVER for Go actually uses a sync streaming server,
683 # but that's mostly because of lack of better name of the enum value.
Jan Tattermusch3b59b0f2016-05-10 14:44:05 -0700684 yield _ping_pong_scenario(
Jan Tattermusch4bd3a7c2016-05-11 09:29:08 -0700685 'go_generic_sync_streaming_qps_unconstrained_%s' % secstr, rpc_type='STREAMING',
686 client_type='SYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER',
Jan Tattermusch5cbccd02016-05-13 16:26:42 -0700687 unconstrained_client='async', use_generic_payload=True,
Jan Tattermuschd27888b2016-05-19 16:11:11 -0700688 secure=secure,
689 categories=[SCALABLE])
Jan Tattermusch3b59b0f2016-05-10 14:44:05 -0700690
Craig Tiller4f2d9ae2016-07-17 14:07:18 -0700691 # TODO(jtattermusch): add scenarios go vs C++
Jan Tattermusch3b59b0f2016-05-10 14:44:05 -0700692
693 def __str__(self):
694 return 'go'
695
murgatroid99b53e5d12016-10-18 09:55:28 -0700696class NodeExpressLanguage:
697
698 def __init__(self):
699 pass
700 self.safename = str(self)
701
702 def worker_cmdline(self):
703 return ['tools/run_tests/performance/run_worker_node.sh',
704 '--benchmark_impl=express']
705
706 def worker_port_offset(self):
707 return 700
708
709 def scenarios(self):
murgatroid99b53e5d12016-10-18 09:55:28 -0700710 yield _ping_pong_scenario(
murgatroid99dabe6bd2016-11-09 11:03:21 -0800711 'node_express_json_unary_ping_pong', rpc_type='UNARY',
murgatroid99b53e5d12016-10-18 09:55:28 -0700712 client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
713 categories=[SCALABLE, SMOKETEST])
714
715 yield _ping_pong_scenario(
murgatroid99dabe6bd2016-11-09 11:03:21 -0800716 'node_express_json_async_unary_qps_unconstrained', rpc_type='UNARY',
murgatroid99b53e5d12016-10-18 09:55:28 -0700717 client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
718 unconstrained_client='async',
719 categories=[SCALABLE, SMOKETEST])
720
murgatroid99b53e5d12016-10-18 09:55:28 -0700721 def __str__(self):
722 return 'node_express'
723
Jan Tattermusch3b59b0f2016-05-10 14:44:05 -0700724
Craig Tillercb2cd262016-04-01 13:59:54 -0700725LANGUAGES = {
726 'c++' : CXXLanguage(),
727 'csharp' : CSharpLanguage(),
728 'node' : NodeLanguage(),
murgatroid99b53e5d12016-10-18 09:55:28 -0700729 'node_express': NodeExpressLanguage(),
Jan Tattermuschde874a12016-04-18 09:21:37 -0700730 'ruby' : RubyLanguage(),
731 'java' : JavaLanguage(),
Ken Payson0482c102016-04-19 12:08:34 -0700732 'python' : PythonLanguage(),
Jan Tattermusch3b59b0f2016-05-10 14:44:05 -0700733 'go' : GoLanguage(),
Craig Tillercb2cd262016-04-01 13:59:54 -0700734}