• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2016 gRPC authors.
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# performance scenario configuration for various languages
16
17import math
18
19WARMUP_SECONDS = 5
20JAVA_WARMUP_SECONDS = 15  # Java needs more warmup time for JIT to kick in.
21BENCHMARK_SECONDS = 30
22
23SMOKETEST = 'smoketest'
24SCALABLE = 'scalable'
25INPROC = 'inproc'
26SWEEP = 'sweep'
27DEFAULT_CATEGORIES = [SCALABLE, SMOKETEST]
28
29SECURE_SECARGS = {
30    'use_test_ca': True,
31    'server_host_override': 'foo.test.google.fr'
32}
33
34HISTOGRAM_PARAMS = {
35    'resolution': 0.01,
36    'max_possible': 60e9,
37}
38
39# target number of RPCs outstanding on across all client channels in
40# non-ping-pong tests (since we can only specify per-channel numbers, the
41# actual target will be slightly higher)
42OUTSTANDING_REQUESTS = {'async': 6400, 'async-limited': 800, 'sync': 1000}
43
44# wide is the number of client channels in multi-channel tests (1 otherwise)
45WIDE = 64
46
47
48def _get_secargs(is_secure):
49    if is_secure:
50        return SECURE_SECARGS
51    else:
52        return None
53
54
55def remove_nonproto_fields(scenario):
56    """Remove special-purpose that contains some extra info about the scenario
57  but don't belong to the ScenarioConfig protobuf message"""
58    scenario.pop('CATEGORIES', None)
59    scenario.pop('CLIENT_LANGUAGE', None)
60    scenario.pop('SERVER_LANGUAGE', None)
61    scenario.pop('EXCLUDED_POLL_ENGINES', None)
62    return scenario
63
64
65def geometric_progression(start, stop, step):
66    n = start
67    while n < stop:
68        yield int(round(n))
69        n *= step
70
71
72def _payload_type(use_generic_payload, req_size, resp_size):
73    r = {}
74    sizes = {
75        'req_size': req_size,
76        'resp_size': resp_size,
77    }
78    if use_generic_payload:
79        r['bytebuf_params'] = sizes
80    else:
81        r['simple_params'] = sizes
82    return r
83
84
85def _load_params(offered_load):
86    r = {}
87    if offered_load is None:
88        r['closed_loop'] = {}
89    else:
90        load = {}
91        load['offered_load'] = offered_load
92        r['poisson'] = load
93    return r
94
95
96def _add_channel_arg(config, key, value):
97    if 'channel_args' in config:
98        channel_args = config['channel_args']
99    else:
100        channel_args = []
101        config['channel_args'] = channel_args
102    arg = {'name': key}
103    if isinstance(value, int):
104        arg['int_value'] = value
105    else:
106        arg['str_value'] = value
107    channel_args.append(arg)
108
109
110def _ping_pong_scenario(name,
111                        rpc_type,
112                        client_type,
113                        server_type,
114                        secure=True,
115                        use_generic_payload=False,
116                        req_size=0,
117                        resp_size=0,
118                        unconstrained_client=None,
119                        client_language=None,
120                        server_language=None,
121                        async_server_threads=0,
122                        client_processes=0,
123                        server_processes=0,
124                        server_threads_per_cq=0,
125                        client_threads_per_cq=0,
126                        warmup_seconds=WARMUP_SECONDS,
127                        categories=DEFAULT_CATEGORIES,
128                        channels=None,
129                        outstanding=None,
130                        num_clients=None,
131                        resource_quota_size=None,
132                        messages_per_stream=None,
133                        excluded_poll_engines=[],
134                        minimal_stack=False,
135                        offered_load=None):
136    """Creates a basic ping pong scenario."""
137    scenario = {
138        'name': name,
139        'num_servers': 1,
140        'num_clients': 1,
141        'client_config': {
142            'client_type': client_type,
143            'security_params': _get_secargs(secure),
144            'outstanding_rpcs_per_channel': 1,
145            'client_channels': 1,
146            'async_client_threads': 1,
147            'client_processes': client_processes,
148            'threads_per_cq': client_threads_per_cq,
149            'rpc_type': rpc_type,
150            'histogram_params': HISTOGRAM_PARAMS,
151            'channel_args': [],
152        },
153        'server_config': {
154            'server_type': server_type,
155            'security_params': _get_secargs(secure),
156            'async_server_threads': async_server_threads,
157            'server_processes': server_processes,
158            'threads_per_cq': server_threads_per_cq,
159            'channel_args': [],
160        },
161        'warmup_seconds': warmup_seconds,
162        'benchmark_seconds': BENCHMARK_SECONDS
163    }
164    if resource_quota_size:
165        scenario['server_config']['resource_quota_size'] = resource_quota_size
166    if use_generic_payload:
167        if server_type != 'ASYNC_GENERIC_SERVER':
168            raise Exception('Use ASYNC_GENERIC_SERVER for generic payload.')
169        scenario['server_config']['payload_config'] = _payload_type(
170            use_generic_payload, req_size, resp_size)
171
172    scenario['client_config']['payload_config'] = _payload_type(
173        use_generic_payload, req_size, resp_size)
174
175    # Optimization target of 'throughput' does not work well with epoll1 polling
176    # engine. Use the default value of 'blend'
177    optimization_target = 'throughput'
178
179    if unconstrained_client:
180        outstanding_calls = outstanding if outstanding is not None else OUTSTANDING_REQUESTS[
181            unconstrained_client]
182        # clamp buffer usage to something reasonable (16 gig for now)
183        MAX_MEMORY_USE = 16 * 1024 * 1024 * 1024
184        if outstanding_calls * max(req_size, resp_size) > MAX_MEMORY_USE:
185            outstanding_calls = max(1,
186                                    MAX_MEMORY_USE / max(req_size, resp_size))
187        wide = channels if channels is not None else WIDE
188        deep = int(math.ceil(1.0 * outstanding_calls / wide))
189
190        scenario[
191            'num_clients'] = num_clients if num_clients is not None else 0  # use as many clients as available.
192        scenario['client_config']['outstanding_rpcs_per_channel'] = deep
193        scenario['client_config']['client_channels'] = wide
194        scenario['client_config']['async_client_threads'] = 0
195        if offered_load is not None:
196            optimization_target = 'latency'
197    else:
198        scenario['client_config']['outstanding_rpcs_per_channel'] = 1
199        scenario['client_config']['client_channels'] = 1
200        scenario['client_config']['async_client_threads'] = 1
201        optimization_target = 'latency'
202
203    scenario['client_config']['load_params'] = _load_params(offered_load)
204
205    optimization_channel_arg = {
206        'name': 'grpc.optimization_target',
207        'str_value': optimization_target
208    }
209    scenario['client_config']['channel_args'].append(optimization_channel_arg)
210    scenario['server_config']['channel_args'].append(optimization_channel_arg)
211
212    if minimal_stack:
213        _add_channel_arg(scenario['client_config'], 'grpc.minimal_stack', 1)
214        _add_channel_arg(scenario['server_config'], 'grpc.minimal_stack', 1)
215
216    if messages_per_stream:
217        scenario['client_config']['messages_per_stream'] = messages_per_stream
218    if client_language:
219        # the CLIENT_LANGUAGE field is recognized by run_performance_tests.py
220        scenario['CLIENT_LANGUAGE'] = client_language
221    if server_language:
222        # the SERVER_LANGUAGE field is recognized by run_performance_tests.py
223        scenario['SERVER_LANGUAGE'] = server_language
224    if categories:
225        scenario['CATEGORIES'] = categories
226    if excluded_poll_engines:
227        # The polling engines for which this scenario is excluded
228        scenario['EXCLUDED_POLL_ENGINES'] = excluded_poll_engines
229    return scenario
230
231
232class CXXLanguage:
233
234    def __init__(self):
235        self.safename = 'cxx'
236
237    def worker_cmdline(self):
238        return ['cmake/build/qps_worker']
239
240    def worker_port_offset(self):
241        return 0
242
243    def scenarios(self):
244        # TODO(ctiller): add 70% load latency test
245        yield _ping_pong_scenario(
246            'cpp_protobuf_async_unary_1channel_100rpcs_1MB',
247            rpc_type='UNARY',
248            client_type='ASYNC_CLIENT',
249            server_type='ASYNC_SERVER',
250            req_size=1024 * 1024,
251            resp_size=1024 * 1024,
252            unconstrained_client='async',
253            outstanding=100,
254            channels=1,
255            num_clients=1,
256            secure=False,
257            categories=[INPROC] + [SCALABLE])
258
259        yield _ping_pong_scenario(
260            'cpp_protobuf_async_streaming_from_client_1channel_1MB',
261            rpc_type='STREAMING_FROM_CLIENT',
262            client_type='ASYNC_CLIENT',
263            server_type='ASYNC_SERVER',
264            req_size=1024 * 1024,
265            resp_size=1024 * 1024,
266            unconstrained_client='async',
267            outstanding=1,
268            channels=1,
269            num_clients=1,
270            secure=False,
271            categories=[SMOKETEST] + [INPROC] + [SCALABLE])
272
273        yield _ping_pong_scenario(
274            'cpp_protobuf_async_unary_75Kqps_600channel_60Krpcs_300Breq_50Bresp',
275            rpc_type='UNARY',
276            client_type='ASYNC_CLIENT',
277            server_type='ASYNC_SERVER',
278            req_size=300,
279            resp_size=50,
280            unconstrained_client='async',
281            outstanding=30000,
282            channels=300,
283            offered_load=37500,
284            secure=False,
285            async_server_threads=16,
286            server_threads_per_cq=1,
287            categories=[SCALABLE])
288
289        for secure in [True, False]:
290            secstr = 'secure' if secure else 'insecure'
291            smoketest_categories = ([SMOKETEST] if secure else [])
292            inproc_categories = ([INPROC] if not secure else [])
293
294            yield _ping_pong_scenario(
295                'cpp_generic_async_streaming_ping_pong_%s' % secstr,
296                rpc_type='STREAMING',
297                client_type='ASYNC_CLIENT',
298                server_type='ASYNC_GENERIC_SERVER',
299                use_generic_payload=True,
300                async_server_threads=1,
301                secure=secure,
302                categories=smoketest_categories + inproc_categories +
303                [SCALABLE])
304
305            yield _ping_pong_scenario(
306                'cpp_generic_async_streaming_qps_unconstrained_%s' % secstr,
307                rpc_type='STREAMING',
308                client_type='ASYNC_CLIENT',
309                server_type='ASYNC_GENERIC_SERVER',
310                unconstrained_client='async',
311                use_generic_payload=True,
312                secure=secure,
313                minimal_stack=not secure,
314                categories=smoketest_categories + inproc_categories +
315                [SCALABLE])
316
317            for mps in geometric_progression(1, 20, 10):
318                yield _ping_pong_scenario(
319                    'cpp_generic_async_streaming_qps_unconstrained_%smps_%s' %
320                    (mps, secstr),
321                    rpc_type='STREAMING',
322                    client_type='ASYNC_CLIENT',
323                    server_type='ASYNC_GENERIC_SERVER',
324                    unconstrained_client='async',
325                    use_generic_payload=True,
326                    secure=secure,
327                    messages_per_stream=mps,
328                    minimal_stack=not secure,
329                    categories=smoketest_categories + inproc_categories +
330                    [SCALABLE])
331
332            for mps in geometric_progression(1, 200, math.sqrt(10)):
333                yield _ping_pong_scenario(
334                    'cpp_generic_async_streaming_qps_unconstrained_%smps_%s' %
335                    (mps, secstr),
336                    rpc_type='STREAMING',
337                    client_type='ASYNC_CLIENT',
338                    server_type='ASYNC_GENERIC_SERVER',
339                    unconstrained_client='async',
340                    use_generic_payload=True,
341                    secure=secure,
342                    messages_per_stream=mps,
343                    minimal_stack=not secure,
344                    categories=[SWEEP])
345
346            yield _ping_pong_scenario(
347                'cpp_generic_async_streaming_qps_1channel_1MBmsg_%s' % secstr,
348                rpc_type='STREAMING',
349                req_size=1024 * 1024,
350                resp_size=1024 * 1024,
351                client_type='ASYNC_CLIENT',
352                server_type='ASYNC_GENERIC_SERVER',
353                unconstrained_client='async',
354                use_generic_payload=True,
355                secure=secure,
356                minimal_stack=not secure,
357                categories=inproc_categories + [SCALABLE],
358                channels=1,
359                outstanding=100)
360
361            yield _ping_pong_scenario(
362                'cpp_generic_async_streaming_qps_unconstrained_64KBmsg_%s' %
363                secstr,
364                rpc_type='STREAMING',
365                req_size=64 * 1024,
366                resp_size=64 * 1024,
367                client_type='ASYNC_CLIENT',
368                server_type='ASYNC_GENERIC_SERVER',
369                unconstrained_client='async',
370                use_generic_payload=True,
371                secure=secure,
372                minimal_stack=not secure,
373                categories=inproc_categories + [SCALABLE])
374
375            yield _ping_pong_scenario(
376                'cpp_generic_async_streaming_qps_unconstrained_1cq_%s' % secstr,
377                rpc_type='STREAMING',
378                client_type='ASYNC_CLIENT',
379                server_type='ASYNC_GENERIC_SERVER',
380                unconstrained_client='async-limited',
381                use_generic_payload=True,
382                secure=secure,
383                client_threads_per_cq=1000000,
384                server_threads_per_cq=1000000,
385                categories=smoketest_categories + inproc_categories +
386                [SCALABLE])
387
388            yield _ping_pong_scenario(
389                'cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_%s'
390                % secstr,
391                rpc_type='STREAMING',
392                client_type='ASYNC_CLIENT',
393                server_type='ASYNC_GENERIC_SERVER',
394                unconstrained_client='async',
395                use_generic_payload=True,
396                secure=secure,
397                client_threads_per_cq=2,
398                server_threads_per_cq=2,
399                categories=inproc_categories + [SCALABLE])
400
401            yield _ping_pong_scenario(
402                'cpp_protobuf_async_streaming_qps_unconstrained_1cq_%s' %
403                secstr,
404                rpc_type='STREAMING',
405                client_type='ASYNC_CLIENT',
406                server_type='ASYNC_SERVER',
407                unconstrained_client='async-limited',
408                secure=secure,
409                client_threads_per_cq=1000000,
410                server_threads_per_cq=1000000,
411                categories=inproc_categories + [SCALABLE])
412
413            yield _ping_pong_scenario(
414                'cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_%s'
415                % secstr,
416                rpc_type='STREAMING',
417                client_type='ASYNC_CLIENT',
418                server_type='ASYNC_SERVER',
419                unconstrained_client='async',
420                secure=secure,
421                client_threads_per_cq=2,
422                server_threads_per_cq=2,
423                categories=inproc_categories + [SCALABLE])
424
425            yield _ping_pong_scenario(
426                'cpp_protobuf_async_unary_qps_unconstrained_1cq_%s' % secstr,
427                rpc_type='UNARY',
428                client_type='ASYNC_CLIENT',
429                server_type='ASYNC_SERVER',
430                unconstrained_client='async-limited',
431                secure=secure,
432                client_threads_per_cq=1000000,
433                server_threads_per_cq=1000000,
434                categories=smoketest_categories + inproc_categories +
435                [SCALABLE])
436
437            yield _ping_pong_scenario(
438                'cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_%s' %
439                secstr,
440                rpc_type='UNARY',
441                client_type='ASYNC_CLIENT',
442                server_type='ASYNC_SERVER',
443                unconstrained_client='async',
444                secure=secure,
445                client_threads_per_cq=2,
446                server_threads_per_cq=2,
447                categories=inproc_categories + [SCALABLE])
448
449            yield _ping_pong_scenario(
450                'cpp_generic_async_streaming_qps_one_server_core_%s' % secstr,
451                rpc_type='STREAMING',
452                client_type='ASYNC_CLIENT',
453                server_type='ASYNC_GENERIC_SERVER',
454                unconstrained_client='async-limited',
455                use_generic_payload=True,
456                async_server_threads=1,
457                minimal_stack=not secure,
458                secure=secure)
459
460            yield _ping_pong_scenario(
461                'cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_%s'
462                % (secstr),
463                rpc_type='UNARY',
464                client_type='ASYNC_CLIENT',
465                server_type='SYNC_SERVER',
466                unconstrained_client='async',
467                secure=secure,
468                minimal_stack=not secure,
469                categories=smoketest_categories + inproc_categories +
470                [SCALABLE])
471
472            yield _ping_pong_scenario(
473                'cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_%s'
474                % (secstr),
475                rpc_type='UNARY',
476                client_type='ASYNC_CLIENT',
477                server_type='ASYNC_SERVER',
478                channels=1,
479                outstanding=64,
480                req_size=128,
481                resp_size=8 * 1024 * 1024,
482                secure=secure,
483                minimal_stack=not secure,
484                categories=inproc_categories + [SCALABLE])
485
486            yield _ping_pong_scenario(
487                'cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_%s'
488                % secstr,
489                rpc_type='STREAMING',
490                client_type='ASYNC_CLIENT',
491                server_type='SYNC_SERVER',
492                unconstrained_client='async',
493                secure=secure,
494                minimal_stack=not secure,
495                categories=smoketest_categories + inproc_categories +
496                [SCALABLE])
497
498            yield _ping_pong_scenario(
499                'cpp_protobuf_async_unary_ping_pong_%s_1MB' % secstr,
500                rpc_type='UNARY',
501                client_type='ASYNC_CLIENT',
502                server_type='ASYNC_SERVER',
503                req_size=1024 * 1024,
504                resp_size=1024 * 1024,
505                secure=secure,
506                minimal_stack=not secure,
507                categories=smoketest_categories + inproc_categories +
508                [SCALABLE])
509
510            for rpc_type in [
511                    'unary', 'streaming', 'streaming_from_client',
512                    'streaming_from_server'
513            ]:
514                for synchronicity in ['sync', 'async']:
515                    yield _ping_pong_scenario(
516                        'cpp_protobuf_%s_%s_ping_pong_%s' %
517                        (synchronicity, rpc_type, secstr),
518                        rpc_type=rpc_type.upper(),
519                        client_type='%s_CLIENT' % synchronicity.upper(),
520                        server_type='%s_SERVER' % synchronicity.upper(),
521                        async_server_threads=1,
522                        minimal_stack=not secure,
523                        secure=secure)
524
525                    for size in geometric_progression(1, 1024 * 1024 * 1024 + 1,
526                                                      8):
527                        yield _ping_pong_scenario(
528                            'cpp_protobuf_%s_%s_qps_unconstrained_%s_%db' %
529                            (synchronicity, rpc_type, secstr, size),
530                            rpc_type=rpc_type.upper(),
531                            req_size=size,
532                            resp_size=size,
533                            client_type='%s_CLIENT' % synchronicity.upper(),
534                            server_type='%s_SERVER' % synchronicity.upper(),
535                            unconstrained_client=synchronicity,
536                            secure=secure,
537                            minimal_stack=not secure,
538                            categories=[SWEEP])
539
540                    yield _ping_pong_scenario(
541                        'cpp_protobuf_%s_%s_qps_unconstrained_%s' %
542                        (synchronicity, rpc_type, secstr),
543                        rpc_type=rpc_type.upper(),
544                        client_type='%s_CLIENT' % synchronicity.upper(),
545                        server_type='%s_SERVER' % synchronicity.upper(),
546                        unconstrained_client=synchronicity,
547                        secure=secure,
548                        minimal_stack=not secure,
549                        server_threads_per_cq=3,
550                        client_threads_per_cq=3,
551                        categories=inproc_categories + [SCALABLE])
552
553                    # TODO(vjpai): Re-enable this test. It has a lot of timeouts
554                    # and hasn't yet been conclusively identified as a test failure
555                    # or race in the library
556                    # yield _ping_pong_scenario(
557                    #     'cpp_protobuf_%s_%s_qps_unconstrained_%s_500kib_resource_quota' % (synchronicity, rpc_type, secstr),
558                    #     rpc_type=rpc_type.upper(),
559                    #     client_type='%s_CLIENT' % synchronicity.upper(),
560                    #     server_type='%s_SERVER' % synchronicity.upper(),
561                    #     unconstrained_client=synchronicity,
562                    #     secure=secure,
563                    #     categories=smoketest_categories+[SCALABLE],
564                    #     resource_quota_size=500*1024)
565
566                    if rpc_type == 'streaming':
567                        for mps in geometric_progression(1, 20, 10):
568                            yield _ping_pong_scenario(
569                                'cpp_protobuf_%s_%s_qps_unconstrained_%smps_%s'
570                                % (synchronicity, rpc_type, mps, secstr),
571                                rpc_type=rpc_type.upper(),
572                                client_type='%s_CLIENT' % synchronicity.upper(),
573                                server_type='%s_SERVER' % synchronicity.upper(),
574                                unconstrained_client=synchronicity,
575                                secure=secure,
576                                messages_per_stream=mps,
577                                minimal_stack=not secure,
578                                categories=inproc_categories + [SCALABLE])
579
580                        for mps in geometric_progression(1, 200, math.sqrt(10)):
581                            yield _ping_pong_scenario(
582                                'cpp_protobuf_%s_%s_qps_unconstrained_%smps_%s'
583                                % (synchronicity, rpc_type, mps, secstr),
584                                rpc_type=rpc_type.upper(),
585                                client_type='%s_CLIENT' % synchronicity.upper(),
586                                server_type='%s_SERVER' % synchronicity.upper(),
587                                unconstrained_client=synchronicity,
588                                secure=secure,
589                                messages_per_stream=mps,
590                                minimal_stack=not secure,
591                                categories=[SWEEP])
592
593                    for channels in geometric_progression(
594                            1, 20000, math.sqrt(10)):
595                        for outstanding in geometric_progression(
596                                1, 200000, math.sqrt(10)):
597                            if synchronicity == 'sync' and outstanding > 1200:
598                                continue
599                            if outstanding < channels: continue
600                            yield _ping_pong_scenario(
601                                'cpp_protobuf_%s_%s_qps_unconstrained_%s_%d_channels_%d_outstanding'
602                                % (synchronicity, rpc_type, secstr, channels,
603                                   outstanding),
604                                rpc_type=rpc_type.upper(),
605                                client_type='%s_CLIENT' % synchronicity.upper(),
606                                server_type='%s_SERVER' % synchronicity.upper(),
607                                unconstrained_client=synchronicity,
608                                secure=secure,
609                                minimal_stack=not secure,
610                                categories=[SWEEP],
611                                channels=channels,
612                                outstanding=outstanding)
613
614    def __str__(self):
615        return 'c++'
616
617
618class CSharpLanguage:
619
620    def __init__(self):
621        self.safename = str(self)
622
623    def worker_cmdline(self):
624        return ['tools/run_tests/performance/run_worker_csharp.sh']
625
626    def worker_port_offset(self):
627        return 100
628
629    def scenarios(self):
630        yield _ping_pong_scenario('csharp_generic_async_streaming_ping_pong',
631                                  rpc_type='STREAMING',
632                                  client_type='ASYNC_CLIENT',
633                                  server_type='ASYNC_GENERIC_SERVER',
634                                  use_generic_payload=True,
635                                  categories=[SMOKETEST, SCALABLE])
636
637        yield _ping_pong_scenario(
638            'csharp_generic_async_streaming_ping_pong_insecure_1MB',
639            rpc_type='STREAMING',
640            client_type='ASYNC_CLIENT',
641            server_type='ASYNC_GENERIC_SERVER',
642            req_size=1024 * 1024,
643            resp_size=1024 * 1024,
644            use_generic_payload=True,
645            secure=False,
646            categories=[SMOKETEST, SCALABLE])
647
648        yield _ping_pong_scenario(
649            'csharp_generic_async_streaming_qps_unconstrained_insecure',
650            rpc_type='STREAMING',
651            client_type='ASYNC_CLIENT',
652            server_type='ASYNC_GENERIC_SERVER',
653            unconstrained_client='async',
654            use_generic_payload=True,
655            secure=False,
656            categories=[SMOKETEST, SCALABLE])
657
658        yield _ping_pong_scenario('csharp_protobuf_async_streaming_ping_pong',
659                                  rpc_type='STREAMING',
660                                  client_type='ASYNC_CLIENT',
661                                  server_type='ASYNC_SERVER')
662
663        yield _ping_pong_scenario('csharp_protobuf_async_unary_ping_pong',
664                                  rpc_type='UNARY',
665                                  client_type='ASYNC_CLIENT',
666                                  server_type='ASYNC_SERVER',
667                                  categories=[SMOKETEST, SCALABLE])
668
669        yield _ping_pong_scenario(
670            'csharp_protobuf_sync_to_async_unary_ping_pong',
671            rpc_type='UNARY',
672            client_type='SYNC_CLIENT',
673            server_type='ASYNC_SERVER')
674
675        yield _ping_pong_scenario(
676            'csharp_protobuf_async_unary_qps_unconstrained',
677            rpc_type='UNARY',
678            client_type='ASYNC_CLIENT',
679            server_type='ASYNC_SERVER',
680            unconstrained_client='async',
681            categories=[SMOKETEST, SCALABLE])
682
683        yield _ping_pong_scenario(
684            'csharp_protobuf_async_streaming_qps_unconstrained',
685            rpc_type='STREAMING',
686            client_type='ASYNC_CLIENT',
687            server_type='ASYNC_SERVER',
688            unconstrained_client='async',
689            categories=[SCALABLE])
690
691        yield _ping_pong_scenario('csharp_to_cpp_protobuf_sync_unary_ping_pong',
692                                  rpc_type='UNARY',
693                                  client_type='SYNC_CLIENT',
694                                  server_type='SYNC_SERVER',
695                                  server_language='c++',
696                                  async_server_threads=1,
697                                  categories=[SMOKETEST, SCALABLE])
698
699        yield _ping_pong_scenario(
700            'csharp_to_cpp_protobuf_async_streaming_ping_pong',
701            rpc_type='STREAMING',
702            client_type='ASYNC_CLIENT',
703            server_type='ASYNC_SERVER',
704            server_language='c++',
705            async_server_threads=1)
706
707        yield _ping_pong_scenario(
708            'csharp_to_cpp_protobuf_async_unary_qps_unconstrained',
709            rpc_type='UNARY',
710            client_type='ASYNC_CLIENT',
711            server_type='ASYNC_SERVER',
712            unconstrained_client='async',
713            server_language='c++',
714            categories=[SCALABLE])
715
716        yield _ping_pong_scenario(
717            'csharp_to_cpp_protobuf_sync_to_async_unary_qps_unconstrained',
718            rpc_type='UNARY',
719            client_type='SYNC_CLIENT',
720            server_type='ASYNC_SERVER',
721            unconstrained_client='sync',
722            server_language='c++',
723            categories=[SCALABLE])
724
725        yield _ping_pong_scenario(
726            'cpp_to_csharp_protobuf_async_unary_qps_unconstrained',
727            rpc_type='UNARY',
728            client_type='ASYNC_CLIENT',
729            server_type='ASYNC_SERVER',
730            unconstrained_client='async',
731            client_language='c++',
732            categories=[SCALABLE])
733
734        yield _ping_pong_scenario('csharp_protobuf_async_unary_ping_pong_1MB',
735                                  rpc_type='UNARY',
736                                  client_type='ASYNC_CLIENT',
737                                  server_type='ASYNC_SERVER',
738                                  req_size=1024 * 1024,
739                                  resp_size=1024 * 1024,
740                                  categories=[SMOKETEST, SCALABLE])
741
742    def __str__(self):
743        return 'csharp'
744
745
746class PythonLanguage:
747
748    def __init__(self):
749        self.safename = 'python'
750
751    def worker_cmdline(self):
752        return ['tools/run_tests/performance/run_worker_python.sh']
753
754    def worker_port_offset(self):
755        return 500
756
757    def scenarios(self):
758        yield _ping_pong_scenario('python_generic_sync_streaming_ping_pong',
759                                  rpc_type='STREAMING',
760                                  client_type='SYNC_CLIENT',
761                                  server_type='ASYNC_GENERIC_SERVER',
762                                  use_generic_payload=True,
763                                  categories=[SMOKETEST, SCALABLE])
764
765        yield _ping_pong_scenario('python_protobuf_sync_streaming_ping_pong',
766                                  rpc_type='STREAMING',
767                                  client_type='SYNC_CLIENT',
768                                  server_type='ASYNC_SERVER')
769
770        yield _ping_pong_scenario('python_protobuf_async_unary_ping_pong',
771                                  rpc_type='UNARY',
772                                  client_type='ASYNC_CLIENT',
773                                  server_type='ASYNC_SERVER')
774
775        yield _ping_pong_scenario('python_protobuf_sync_unary_ping_pong',
776                                  rpc_type='UNARY',
777                                  client_type='SYNC_CLIENT',
778                                  server_type='ASYNC_SERVER',
779                                  categories=[SMOKETEST, SCALABLE])
780
781        yield _ping_pong_scenario(
782            'python_protobuf_sync_unary_qps_unconstrained',
783            rpc_type='UNARY',
784            client_type='SYNC_CLIENT',
785            server_type='ASYNC_SERVER',
786            unconstrained_client='sync')
787
788        yield _ping_pong_scenario(
789            'python_protobuf_sync_streaming_qps_unconstrained',
790            rpc_type='STREAMING',
791            client_type='SYNC_CLIENT',
792            server_type='ASYNC_SERVER',
793            unconstrained_client='sync')
794
795        yield _ping_pong_scenario('python_to_cpp_protobuf_sync_unary_ping_pong',
796                                  rpc_type='UNARY',
797                                  client_type='SYNC_CLIENT',
798                                  server_type='ASYNC_SERVER',
799                                  server_language='c++',
800                                  async_server_threads=0,
801                                  categories=[SMOKETEST, SCALABLE])
802
803        yield _ping_pong_scenario(
804            'python_to_cpp_protobuf_sync_streaming_ping_pong',
805            rpc_type='STREAMING',
806            client_type='SYNC_CLIENT',
807            server_type='ASYNC_SERVER',
808            server_language='c++',
809            async_server_threads=1)
810
811        yield _ping_pong_scenario('python_protobuf_sync_unary_ping_pong_1MB',
812                                  rpc_type='UNARY',
813                                  client_type='SYNC_CLIENT',
814                                  server_type='ASYNC_SERVER',
815                                  req_size=1024 * 1024,
816                                  resp_size=1024 * 1024,
817                                  categories=[SMOKETEST, SCALABLE])
818
819    def __str__(self):
820        return 'python'
821
822
823class PythonAsyncIOLanguage:
824
825    def __init__(self):
826        self.safename = 'python_asyncio'
827
828    def worker_cmdline(self):
829        return ['tools/run_tests/performance/run_worker_python_asyncio.sh']
830
831    def worker_port_offset(self):
832        return 1200
833
834    def scenarios(self):
835        for outstanding in [64, 128, 256, 512]:
836            for channels in [1, 4]:
837                yield _ping_pong_scenario(
838                    'python_asyncio_protobuf_async_unary_ping_pong_%dx%d_max' %
839                    (
840                        outstanding,
841                        channels,
842                    ),
843                    rpc_type='UNARY',
844                    client_type='ASYNC_CLIENT',
845                    server_type='ASYNC_SERVER',
846                    outstanding=outstanding * channels,
847                    channels=channels,
848                    client_processes=0,
849                    server_processes=0,
850                    unconstrained_client='async',
851                    categories=[SCALABLE])
852
853            yield _ping_pong_scenario(
854                'python_asyncio_protobuf_async_unary_ping_pong_%d_1thread' %
855                outstanding,
856                rpc_type='UNARY',
857                client_type='ASYNC_CLIENT',
858                server_type='ASYNC_SERVER',
859                outstanding=outstanding,
860                channels=1,
861                client_processes=1,
862                server_processes=1,
863                unconstrained_client='async',
864                categories=[SCALABLE])
865
866        yield _ping_pong_scenario(
867            'python_asyncio_generic_async_streaming_ping_pong',
868            rpc_type='STREAMING',
869            client_type='ASYNC_CLIENT',
870            server_type='ASYNC_GENERIC_SERVER',
871            channels=1,
872            client_processes=1,
873            server_processes=1,
874            use_generic_payload=True,
875            categories=[SMOKETEST, SCALABLE])
876
877        yield _ping_pong_scenario(
878            'python_asyncio_protobuf_async_streaming_ping_pong',
879            rpc_type='STREAMING',
880            client_type='ASYNC_CLIENT',
881            server_type='ASYNC_SERVER',
882            channels=1,
883            client_processes=1,
884            server_processes=1,
885            categories=[SMOKETEST, SCALABLE])
886
887        yield _ping_pong_scenario(
888            'python_asyncio_protobuf_async_unary_ping_pong',
889            rpc_type='UNARY',
890            client_type='ASYNC_CLIENT',
891            server_type='ASYNC_SERVER',
892            client_processes=1,
893            server_processes=1,
894            categories=[SMOKETEST, SCALABLE])
895
896        yield _ping_pong_scenario(
897            'python_asyncio_protobuf_async_unary_ping_pong',
898            rpc_type='UNARY',
899            client_type='ASYNC_CLIENT',
900            server_type='ASYNC_SERVER',
901            channels=1,
902            client_processes=1,
903            server_processes=1,
904            categories=[SMOKETEST, SCALABLE])
905
906        yield _ping_pong_scenario(
907            'python_asyncio_protobuf_async_unary_qps_unconstrained',
908            rpc_type='UNARY',
909            client_type='ASYNC_CLIENT',
910            server_type='ASYNC_SERVER',
911            channels=1,
912            unconstrained_client='async')
913
914        yield _ping_pong_scenario(
915            'python_asyncio_protobuf_async_streaming_qps_unconstrained',
916            rpc_type='STREAMING',
917            client_type='ASYNC_CLIENT',
918            server_type='ASYNC_SERVER',
919            channels=1,
920            unconstrained_client='async')
921
922        yield _ping_pong_scenario(
923            'python_asyncio_to_cpp_protobuf_async_unary_ping_pong_1thread',
924            rpc_type='UNARY',
925            client_type='ASYNC_CLIENT',
926            server_type='ASYNC_SERVER',
927            server_language='c++',
928            channels=1,
929            client_processes=1,
930            unconstrained_client='async',
931            categories=[SMOKETEST, SCALABLE])
932
933        yield _ping_pong_scenario(
934            'python_asyncio_to_cpp_protobuf_async_unary_ping_pong_max',
935            rpc_type='UNARY',
936            client_type='ASYNC_CLIENT',
937            server_type='ASYNC_SERVER',
938            unconstrained_client='async',
939            channels=1,
940            client_processes=0,
941            server_language='c++',
942            categories=[SMOKETEST, SCALABLE])
943
944        yield _ping_pong_scenario(
945            'python_asyncio_to_cpp_protobuf_sync_streaming_ping_pong_1thread',
946            rpc_type='STREAMING',
947            client_type='ASYNC_CLIENT',
948            server_type='ASYNC_SERVER',
949            channels=1,
950            client_processes=1,
951            server_processes=1,
952            unconstrained_client='async',
953            server_language='c++')
954
955        yield _ping_pong_scenario(
956            'python_asyncio_protobuf_async_unary_ping_pong_1MB',
957            rpc_type='UNARY',
958            client_type='ASYNC_CLIENT',
959            server_type='ASYNC_SERVER',
960            req_size=1024 * 1024,
961            resp_size=1024 * 1024,
962            channels=1,
963            client_processes=1,
964            server_processes=1,
965            categories=[SMOKETEST, SCALABLE])
966
967    def __str__(self):
968        return 'python_asyncio'
969
970
971class RubyLanguage:
972
973    def __init__(self):
974        pass
975        self.safename = str(self)
976
977    def worker_cmdline(self):
978        return ['tools/run_tests/performance/run_worker_ruby.sh']
979
980    def worker_port_offset(self):
981        return 300
982
983    def scenarios(self):
984        yield _ping_pong_scenario('ruby_protobuf_sync_streaming_ping_pong',
985                                  rpc_type='STREAMING',
986                                  client_type='SYNC_CLIENT',
987                                  server_type='SYNC_SERVER',
988                                  categories=[SMOKETEST, SCALABLE])
989
990        yield _ping_pong_scenario('ruby_protobuf_unary_ping_pong',
991                                  rpc_type='UNARY',
992                                  client_type='SYNC_CLIENT',
993                                  server_type='SYNC_SERVER',
994                                  categories=[SMOKETEST, SCALABLE])
995
996        yield _ping_pong_scenario('ruby_protobuf_sync_unary_qps_unconstrained',
997                                  rpc_type='UNARY',
998                                  client_type='SYNC_CLIENT',
999                                  server_type='SYNC_SERVER',
1000                                  unconstrained_client='sync')
1001
1002        yield _ping_pong_scenario(
1003            'ruby_protobuf_sync_streaming_qps_unconstrained',
1004            rpc_type='STREAMING',
1005            client_type='SYNC_CLIENT',
1006            server_type='SYNC_SERVER',
1007            unconstrained_client='sync')
1008
1009        yield _ping_pong_scenario('ruby_to_cpp_protobuf_sync_unary_ping_pong',
1010                                  rpc_type='UNARY',
1011                                  client_type='SYNC_CLIENT',
1012                                  server_type='SYNC_SERVER',
1013                                  server_language='c++',
1014                                  async_server_threads=1)
1015
1016        yield _ping_pong_scenario(
1017            'ruby_to_cpp_protobuf_sync_streaming_ping_pong',
1018            rpc_type='STREAMING',
1019            client_type='SYNC_CLIENT',
1020            server_type='SYNC_SERVER',
1021            server_language='c++',
1022            async_server_threads=1)
1023
1024        yield _ping_pong_scenario('ruby_protobuf_unary_ping_pong_1MB',
1025                                  rpc_type='UNARY',
1026                                  client_type='SYNC_CLIENT',
1027                                  server_type='SYNC_SERVER',
1028                                  req_size=1024 * 1024,
1029                                  resp_size=1024 * 1024,
1030                                  categories=[SMOKETEST, SCALABLE])
1031
1032    def __str__(self):
1033        return 'ruby'
1034
1035
1036class Php7Language:
1037
1038    def __init__(self, php7_protobuf_c=False):
1039        pass
1040        self.php7_protobuf_c = php7_protobuf_c
1041        self.safename = str(self)
1042
1043    def worker_cmdline(self):
1044        if self.php7_protobuf_c:
1045            return [
1046                'tools/run_tests/performance/run_worker_php.sh',
1047                '--use_protobuf_c_extension'
1048            ]
1049        return ['tools/run_tests/performance/run_worker_php.sh']
1050
1051    def worker_port_offset(self):
1052        if self.php7_protobuf_c:
1053            return 900
1054        return 800
1055
1056    def scenarios(self):
1057        php7_extension_mode = 'php7_protobuf_php_extension'
1058        if self.php7_protobuf_c:
1059            php7_extension_mode = 'php7_protobuf_c_extension'
1060
1061        yield _ping_pong_scenario('%s_to_cpp_protobuf_sync_unary_ping_pong' %
1062                                  php7_extension_mode,
1063                                  rpc_type='UNARY',
1064                                  client_type='SYNC_CLIENT',
1065                                  server_type='SYNC_SERVER',
1066                                  server_language='c++',
1067                                  async_server_threads=1)
1068
1069        yield _ping_pong_scenario(
1070            '%s_to_cpp_protobuf_sync_streaming_ping_pong' % php7_extension_mode,
1071            rpc_type='STREAMING',
1072            client_type='SYNC_CLIENT',
1073            server_type='SYNC_SERVER',
1074            server_language='c++',
1075            async_server_threads=1)
1076
1077        # TODO(ddyihai): Investigate why when async_server_threads=1/CPU usage 340%, the QPS performs
1078        # better than async_server_threads=0/CPU usage 490%.
1079        yield _ping_pong_scenario(
1080            '%s_to_cpp_protobuf_sync_unary_qps_unconstrained' %
1081            php7_extension_mode,
1082            rpc_type='UNARY',
1083            client_type='SYNC_CLIENT',
1084            server_type='ASYNC_SERVER',
1085            server_language='c++',
1086            outstanding=1,
1087            async_server_threads=1,
1088            unconstrained_client='sync')
1089
1090        yield _ping_pong_scenario(
1091            '%s_to_cpp_protobuf_sync_streaming_qps_unconstrained' %
1092            php7_extension_mode,
1093            rpc_type='STREAMING',
1094            client_type='SYNC_CLIENT',
1095            server_type='ASYNC_SERVER',
1096            server_language='c++',
1097            outstanding=1,
1098            async_server_threads=1,
1099            unconstrained_client='sync')
1100
1101    def __str__(self):
1102        if self.php7_protobuf_c:
1103            return 'php7_protobuf_c'
1104        return 'php7'
1105
1106
1107class JavaLanguage:
1108
1109    def __init__(self):
1110        pass
1111        self.safename = str(self)
1112
1113    def worker_cmdline(self):
1114        return ['tools/run_tests/performance/run_worker_java.sh']
1115
1116    def worker_port_offset(self):
1117        return 400
1118
1119    def scenarios(self):
1120        for secure in [True, False]:
1121            secstr = 'secure' if secure else 'insecure'
1122            smoketest_categories = ([SMOKETEST] if secure else []) + [SCALABLE]
1123
1124            yield _ping_pong_scenario(
1125                'java_generic_async_streaming_ping_pong_%s' % secstr,
1126                rpc_type='STREAMING',
1127                client_type='ASYNC_CLIENT',
1128                server_type='ASYNC_GENERIC_SERVER',
1129                use_generic_payload=True,
1130                async_server_threads=1,
1131                secure=secure,
1132                warmup_seconds=JAVA_WARMUP_SECONDS,
1133                categories=smoketest_categories)
1134
1135            yield _ping_pong_scenario(
1136                'java_protobuf_async_streaming_ping_pong_%s' % secstr,
1137                rpc_type='STREAMING',
1138                client_type='ASYNC_CLIENT',
1139                server_type='ASYNC_SERVER',
1140                async_server_threads=1,
1141                secure=secure,
1142                warmup_seconds=JAVA_WARMUP_SECONDS)
1143
1144            yield _ping_pong_scenario('java_protobuf_async_unary_ping_pong_%s' %
1145                                      secstr,
1146                                      rpc_type='UNARY',
1147                                      client_type='ASYNC_CLIENT',
1148                                      server_type='ASYNC_SERVER',
1149                                      async_server_threads=1,
1150                                      secure=secure,
1151                                      warmup_seconds=JAVA_WARMUP_SECONDS,
1152                                      categories=smoketest_categories)
1153
1154            yield _ping_pong_scenario('java_protobuf_unary_ping_pong_%s' %
1155                                      secstr,
1156                                      rpc_type='UNARY',
1157                                      client_type='SYNC_CLIENT',
1158                                      server_type='SYNC_SERVER',
1159                                      async_server_threads=1,
1160                                      secure=secure,
1161                                      warmup_seconds=JAVA_WARMUP_SECONDS)
1162
1163            yield _ping_pong_scenario(
1164                'java_protobuf_async_unary_qps_unconstrained_%s' % secstr,
1165                rpc_type='UNARY',
1166                client_type='ASYNC_CLIENT',
1167                server_type='ASYNC_SERVER',
1168                unconstrained_client='async',
1169                secure=secure,
1170                warmup_seconds=JAVA_WARMUP_SECONDS,
1171                categories=smoketest_categories + [SCALABLE])
1172
1173            yield _ping_pong_scenario(
1174                'java_protobuf_async_streaming_qps_unconstrained_%s' % secstr,
1175                rpc_type='STREAMING',
1176                client_type='ASYNC_CLIENT',
1177                server_type='ASYNC_SERVER',
1178                unconstrained_client='async',
1179                secure=secure,
1180                warmup_seconds=JAVA_WARMUP_SECONDS,
1181                categories=[SCALABLE])
1182
1183            yield _ping_pong_scenario(
1184                'java_generic_async_streaming_qps_unconstrained_%s' % secstr,
1185                rpc_type='STREAMING',
1186                client_type='ASYNC_CLIENT',
1187                server_type='ASYNC_GENERIC_SERVER',
1188                unconstrained_client='async',
1189                use_generic_payload=True,
1190                secure=secure,
1191                warmup_seconds=JAVA_WARMUP_SECONDS,
1192                categories=[SCALABLE])
1193
1194            yield _ping_pong_scenario(
1195                'java_generic_async_streaming_qps_one_server_core_%s' % secstr,
1196                rpc_type='STREAMING',
1197                client_type='ASYNC_CLIENT',
1198                server_type='ASYNC_GENERIC_SERVER',
1199                unconstrained_client='async-limited',
1200                use_generic_payload=True,
1201                async_server_threads=1,
1202                secure=secure,
1203                warmup_seconds=JAVA_WARMUP_SECONDS)
1204
1205            # TODO(jtattermusch): add scenarios java vs C++
1206
1207    def __str__(self):
1208        return 'java'
1209
1210
1211class GoLanguage:
1212
1213    def __init__(self):
1214        pass
1215        self.safename = str(self)
1216
1217    def worker_cmdline(self):
1218        return ['tools/run_tests/performance/run_worker_go.sh']
1219
1220    def worker_port_offset(self):
1221        return 600
1222
1223    def scenarios(self):
1224        for secure in [True, False]:
1225            secstr = 'secure' if secure else 'insecure'
1226            smoketest_categories = ([SMOKETEST] if secure else []) + [SCALABLE]
1227
1228            # ASYNC_GENERIC_SERVER for Go actually uses a sync streaming server,
1229            # but that's mostly because of lack of better name of the enum value.
1230            yield _ping_pong_scenario('go_generic_sync_streaming_ping_pong_%s' %
1231                                      secstr,
1232                                      rpc_type='STREAMING',
1233                                      client_type='SYNC_CLIENT',
1234                                      server_type='ASYNC_GENERIC_SERVER',
1235                                      use_generic_payload=True,
1236                                      async_server_threads=1,
1237                                      secure=secure,
1238                                      categories=smoketest_categories)
1239
1240            yield _ping_pong_scenario(
1241                'go_protobuf_sync_streaming_ping_pong_%s' % secstr,
1242                rpc_type='STREAMING',
1243                client_type='SYNC_CLIENT',
1244                server_type='SYNC_SERVER',
1245                async_server_threads=1,
1246                secure=secure)
1247
1248            yield _ping_pong_scenario('go_protobuf_sync_unary_ping_pong_%s' %
1249                                      secstr,
1250                                      rpc_type='UNARY',
1251                                      client_type='SYNC_CLIENT',
1252                                      server_type='SYNC_SERVER',
1253                                      async_server_threads=1,
1254                                      secure=secure,
1255                                      categories=smoketest_categories)
1256
1257            # unconstrained_client='async' is intended (client uses goroutines)
1258            yield _ping_pong_scenario(
1259                'go_protobuf_sync_unary_qps_unconstrained_%s' % secstr,
1260                rpc_type='UNARY',
1261                client_type='SYNC_CLIENT',
1262                server_type='SYNC_SERVER',
1263                unconstrained_client='async',
1264                secure=secure,
1265                categories=smoketest_categories + [SCALABLE])
1266
1267            # unconstrained_client='async' is intended (client uses goroutines)
1268            yield _ping_pong_scenario(
1269                'go_protobuf_sync_streaming_qps_unconstrained_%s' % secstr,
1270                rpc_type='STREAMING',
1271                client_type='SYNC_CLIENT',
1272                server_type='SYNC_SERVER',
1273                unconstrained_client='async',
1274                secure=secure,
1275                categories=[SCALABLE])
1276
1277            # unconstrained_client='async' is intended (client uses goroutines)
1278            # ASYNC_GENERIC_SERVER for Go actually uses a sync streaming server,
1279            # but that's mostly because of lack of better name of the enum value.
1280            yield _ping_pong_scenario(
1281                'go_generic_sync_streaming_qps_unconstrained_%s' % secstr,
1282                rpc_type='STREAMING',
1283                client_type='SYNC_CLIENT',
1284                server_type='ASYNC_GENERIC_SERVER',
1285                unconstrained_client='async',
1286                use_generic_payload=True,
1287                secure=secure,
1288                categories=[SCALABLE])
1289
1290            # TODO(jtattermusch): add scenarios go vs C++
1291
1292    def __str__(self):
1293        return 'go'
1294
1295
1296class NodeLanguage:
1297
1298    def __init__(self, node_purejs=False):
1299        pass
1300        self.node_purejs = node_purejs
1301        self.safename = str(self)
1302
1303    def worker_cmdline(self):
1304        fixture = 'native_js' if self.node_purejs else 'native_native'
1305        return [
1306            'tools/run_tests/performance/run_worker_node.sh', fixture,
1307            '--benchmark_impl=grpc'
1308        ]
1309
1310    def worker_port_offset(self):
1311        if self.node_purejs:
1312            return 1100
1313        return 1000
1314
1315    def scenarios(self):
1316        node_implementation = 'node_purejs' if self.node_purejs else 'node'
1317        for secure in [True, False]:
1318            secstr = 'secure' if secure else 'insecure'
1319            smoketest_categories = ([SMOKETEST] if secure else []) + [SCALABLE]
1320
1321            yield _ping_pong_scenario(
1322                '%s_to_node_generic_async_streaming_ping_pong_%s' %
1323                (node_implementation, secstr),
1324                rpc_type='STREAMING',
1325                client_type='ASYNC_CLIENT',
1326                server_type='ASYNC_GENERIC_SERVER',
1327                server_language='node',
1328                use_generic_payload=True,
1329                async_server_threads=1,
1330                secure=secure,
1331                categories=smoketest_categories)
1332
1333            yield _ping_pong_scenario(
1334                '%s_to_node_protobuf_async_streaming_ping_pong_%s' %
1335                (node_implementation, secstr),
1336                rpc_type='STREAMING',
1337                client_type='ASYNC_CLIENT',
1338                server_type='ASYNC_SERVER',
1339                server_language='node',
1340                async_server_threads=1,
1341                secure=secure)
1342
1343            yield _ping_pong_scenario(
1344                '%s_to_node_protobuf_async_unary_ping_pong_%s' %
1345                (node_implementation, secstr),
1346                rpc_type='UNARY',
1347                client_type='ASYNC_CLIENT',
1348                server_type='ASYNC_SERVER',
1349                server_language='node',
1350                async_server_threads=1,
1351                secure=secure,
1352                categories=smoketest_categories)
1353
1354            yield _ping_pong_scenario(
1355                '%s_to_node_protobuf_async_unary_qps_unconstrained_%s' %
1356                (node_implementation, secstr),
1357                rpc_type='UNARY',
1358                client_type='ASYNC_CLIENT',
1359                server_type='ASYNC_SERVER',
1360                server_language='node',
1361                unconstrained_client='async',
1362                secure=secure,
1363                categories=smoketest_categories + [SCALABLE])
1364
1365            yield _ping_pong_scenario(
1366                '%s_to_node_protobuf_async_streaming_qps_unconstrained_%s' %
1367                (node_implementation, secstr),
1368                rpc_type='STREAMING',
1369                client_type='ASYNC_CLIENT',
1370                server_type='ASYNC_SERVER',
1371                server_language='node',
1372                unconstrained_client='async',
1373                secure=secure,
1374                categories=[SCALABLE])
1375
1376            yield _ping_pong_scenario(
1377                '%s_to_node_generic_async_streaming_qps_unconstrained_%s' %
1378                (node_implementation, secstr),
1379                rpc_type='STREAMING',
1380                client_type='ASYNC_CLIENT',
1381                server_type='ASYNC_GENERIC_SERVER',
1382                server_language='node',
1383                unconstrained_client='async',
1384                use_generic_payload=True,
1385                secure=secure,
1386                categories=[SCALABLE])
1387
1388            # TODO(murgatroid99): add scenarios node vs C++
1389
1390    def __str__(self):
1391        if self.node_purejs:
1392            return 'node_purejs'
1393        return 'node'
1394
1395
1396LANGUAGES = {
1397    'c++': CXXLanguage(),
1398    'csharp': CSharpLanguage(),
1399    'ruby': RubyLanguage(),
1400    'php7': Php7Language(),
1401    'php7_protobuf_c': Php7Language(php7_protobuf_c=True),
1402    'java': JavaLanguage(),
1403    'python': PythonLanguage(),
1404    'python_asyncio': PythonAsyncIOLanguage(),
1405    'go': GoLanguage(),
1406    'node': NodeLanguage(),
1407    'node_purejs': NodeLanguage(node_purejs=True)
1408}
1409