xref: /aosp_15_r20/external/grpc-grpc-java/benchmarks/src/main/java/io/grpc/benchmarks/qps/ClientConfiguration.java (revision e07d83d3ffcef9ecfc9f7f475418ec639ff0e5fe)
1 /*
2  * Copyright 2015 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc.benchmarks.qps;
18 
19 import static io.grpc.benchmarks.Utils.parseBoolean;
20 import static java.lang.Integer.parseInt;
21 import static java.util.Arrays.asList;
22 
23 import io.grpc.ManagedChannel;
24 import io.grpc.benchmarks.Transport;
25 import io.grpc.benchmarks.Utils;
26 import io.grpc.benchmarks.proto.Control.RpcType;
27 import io.grpc.benchmarks.proto.Messages;
28 import io.grpc.benchmarks.proto.Messages.PayloadType;
29 import io.grpc.internal.testing.TestUtils;
30 import java.io.IOException;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.LinkedHashSet;
34 import java.util.Set;
35 
36 /**
37  * Configuration options for benchmark clients.
38  */
39 public class ClientConfiguration implements Configuration {
40   private static final ClientConfiguration DEFAULT = new ClientConfiguration();
41 
42   Transport transport = Transport.NETTY_NIO;
43   boolean tls;
44   boolean testca;
45   String authorityOverride = TestUtils.TEST_SERVER_HOST;
46   boolean useDefaultCiphers;
47   boolean directExecutor;
48   String target;
49   int channels = 4;
50   int outstandingRpcsPerChannel = 10;
51   int serverPayload;
52   int clientPayload;
53   int flowControlWindow = Utils.DEFAULT_FLOW_CONTROL_WINDOW;
54   // seconds
55   int duration = 60;
56   // seconds
57   int warmupDuration = 10;
58   int targetQps;
59   String histogramFile;
60   RpcType rpcType = RpcType.UNARY;
61   PayloadType payloadType = PayloadType.COMPRESSABLE;
62 
ClientConfiguration()63   private ClientConfiguration() {
64   }
65 
newChannel()66   public ManagedChannel newChannel() throws IOException {
67     return Utils.newClientChannel(transport, target, tls, testca, authorityOverride,
68         flowControlWindow, directExecutor);
69   }
70 
newRequest()71   public Messages.SimpleRequest newRequest() {
72     return Utils.makeRequest(payloadType, clientPayload, serverPayload);
73   }
74 
75   /**
76    * Constructs a builder for configuring a client application with supported parameters. If no
77    * parameters are provided, all parameters are assumed to be supported.
78    */
newBuilder(ClientParam... supportedParams)79   static Builder newBuilder(ClientParam... supportedParams) {
80     return new Builder(supportedParams);
81   }
82 
83   static final class Builder extends AbstractConfigurationBuilder<ClientConfiguration> {
84     private final Collection<Param> supportedParams;
85 
Builder(ClientParam... supportedParams)86     private Builder(ClientParam... supportedParams) {
87       this.supportedParams = supportedOptionsSet(supportedParams);
88     }
89 
90     @Override
newConfiguration()91     protected ClientConfiguration newConfiguration() {
92       return new ClientConfiguration();
93     }
94 
95     @Override
getParams()96     protected Collection<Param> getParams() {
97       return supportedParams;
98     }
99 
100     @Override
build0(ClientConfiguration config)101     protected ClientConfiguration build0(ClientConfiguration config) {
102       if (config.tls) {
103         if (!config.transport.tlsSupported) {
104           throw new IllegalArgumentException(
105               "Transport " + config.transport.name().toLowerCase() + " does not support TLS.");
106         }
107       }
108 
109       // Verify that the address type is correct for the transport type.
110       config.transport.validateSocketAddress(config.target);
111 
112       return config;
113     }
114 
supportedOptionsSet(ClientParam... supportedParams)115     private static Set<Param> supportedOptionsSet(ClientParam... supportedParams) {
116       if (supportedParams.length == 0) {
117         // If no options are supplied, default to including all options.
118         supportedParams = ClientParam.values();
119       }
120       return Collections.unmodifiableSet(new LinkedHashSet<Param>(asList(supportedParams)));
121     }
122   }
123 
124   enum ClientParam implements AbstractConfigurationBuilder.Param {
125     ADDRESS("STR", "Socket address (host:port) or Unix Domain Socket file name "
126         + "(unix:///path/to/file), depending on the transport selected.", null, true) {
127       @Override
setClientValue(ClientConfiguration config, String value)128       protected void setClientValue(ClientConfiguration config, String value) {
129         config.target = value;
130       }
131     },
132     CHANNELS("INT", "Number of Channels.", "" + DEFAULT.channels) {
133       @Override
setClientValue(ClientConfiguration config, String value)134       protected void setClientValue(ClientConfiguration config, String value) {
135         config.channels = parseInt(value);
136       }
137     },
138     OUTSTANDING_RPCS("INT", "Number of outstanding RPCs per Channel.",
139         "" + DEFAULT.outstandingRpcsPerChannel) {
140       @Override
setClientValue(ClientConfiguration config, String value)141       protected void setClientValue(ClientConfiguration config, String value) {
142         config.outstandingRpcsPerChannel = parseInt(value);
143       }
144     },
145     CLIENT_PAYLOAD("BYTES", "Payload Size of the Request.", "" + DEFAULT.clientPayload) {
146       @Override
setClientValue(ClientConfiguration config, String value)147       protected void setClientValue(ClientConfiguration config, String value) {
148         config.clientPayload = parseInt(value);
149       }
150     },
151     SERVER_PAYLOAD("BYTES", "Payload Size of the Response.", "" + DEFAULT.serverPayload) {
152       @Override
setClientValue(ClientConfiguration config, String value)153       protected void setClientValue(ClientConfiguration config, String value) {
154         config.serverPayload = parseInt(value);
155       }
156     },
157     TLS("", "Enable TLS.", "" + DEFAULT.tls) {
158       @Override
setClientValue(ClientConfiguration config, String value)159       protected void setClientValue(ClientConfiguration config, String value) {
160         config.tls = parseBoolean(value);
161       }
162     },
163     TESTCA("", "Use the provided Test Certificate for TLS.", "" + DEFAULT.testca) {
164       @Override
setClientValue(ClientConfiguration config, String value)165       protected void setClientValue(ClientConfiguration config, String value) {
166         config.testca = parseBoolean(value);
167       }
168     },
169     TRANSPORT("STR", Transport.getDescriptionString(), DEFAULT.transport.name().toLowerCase()) {
170       @Override
setClientValue(ClientConfiguration config, String value)171       protected void setClientValue(ClientConfiguration config, String value) {
172         config.transport = Transport.valueOf(value.toUpperCase());
173       }
174     },
175     DURATION("SECONDS", "Duration of the benchmark.", "" + DEFAULT.duration) {
176       @Override
setClientValue(ClientConfiguration config, String value)177       protected void setClientValue(ClientConfiguration config, String value) {
178         config.duration = parseInt(value);
179       }
180     },
181     WARMUP_DURATION("SECONDS", "Warmup Duration of the benchmark.", "" + DEFAULT.warmupDuration) {
182       @Override
setClientValue(ClientConfiguration config, String value)183       protected void setClientValue(ClientConfiguration config, String value) {
184         config.warmupDuration = parseInt(value);
185       }
186     },
187     DIRECTEXECUTOR("",
188         "Don't use a threadpool for RPC calls, instead execute calls directly "
189             + "in the transport thread.", "" + DEFAULT.directExecutor) {
190       @Override
setClientValue(ClientConfiguration config, String value)191       protected void setClientValue(ClientConfiguration config, String value) {
192         config.directExecutor = parseBoolean(value);
193       }
194     },
195     SAVE_HISTOGRAM("FILE", "Write the histogram with the latency recordings to file.", null) {
196       @Override
setClientValue(ClientConfiguration config, String value)197       protected void setClientValue(ClientConfiguration config, String value) {
198         config.histogramFile = value;
199       }
200     },
201     STREAMING_RPCS("", "Use Streaming RPCs.", "false") {
202       @Override
setClientValue(ClientConfiguration config, String value)203       protected void setClientValue(ClientConfiguration config, String value) {
204         config.rpcType = RpcType.STREAMING;
205       }
206     },
207     FLOW_CONTROL_WINDOW("BYTES", "The HTTP/2 flow control window.",
208         "" + DEFAULT.flowControlWindow) {
209       @Override
setClientValue(ClientConfiguration config, String value)210       protected void setClientValue(ClientConfiguration config, String value) {
211         config.flowControlWindow = parseInt(value);
212       }
213     },
214     TARGET_QPS("INT", "Average number of QPS to shoot for.", "" + DEFAULT.targetQps, true) {
215       @Override
setClientValue(ClientConfiguration config, String value)216       protected void setClientValue(ClientConfiguration config, String value) {
217         config.targetQps = parseInt(value);
218       }
219     };
220 
221     private final String type;
222     private final String description;
223     private final String defaultValue;
224     private final boolean required;
225 
ClientParam(String type, String description, String defaultValue)226     ClientParam(String type, String description, String defaultValue) {
227       this(type, description, defaultValue, false);
228     }
229 
ClientParam(String type, String description, String defaultValue, boolean required)230     ClientParam(String type, String description, String defaultValue, boolean required) {
231       this.type = type;
232       this.description = description;
233       this.defaultValue = defaultValue;
234       this.required = required;
235     }
236 
237     @Override
getName()238     public String getName() {
239       return name().toLowerCase();
240     }
241 
242     @Override
getType()243     public String getType() {
244       return type;
245     }
246 
247     @Override
getDescription()248     public String getDescription() {
249       return description;
250     }
251 
252     @Override
getDefaultValue()253     public String getDefaultValue() {
254       return defaultValue;
255     }
256 
257     @Override
isRequired()258     public boolean isRequired() {
259       return required;
260     }
261 
262     @Override
setValue(Configuration config, String value)263     public void setValue(Configuration config, String value) {
264       setClientValue((ClientConfiguration) config, value);
265     }
266 
setClientValue(ClientConfiguration config, String value)267     protected abstract void setClientValue(ClientConfiguration config, String value);
268   }
269 }
270