grpc benchmarks: add ssl options and capabilities

Task-number: QTBUG-133254
Change-Id: I517d524e1d6c953791a11ba5351cdfd1b433cee2
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
This commit is contained in:
Dennis Oberst 2025-01-27 13:21:15 +01:00
parent dfc3306e1a
commit 3dfc6c66b2
5 changed files with 170 additions and 24 deletions

View File

@ -61,6 +61,7 @@ qt_internal_add_executable(
LIBRARIES
protobuf::libprotobuf
gRPC::grpc++
Qt::Core
INCLUDE_DIRECTORIES
"${proto_out_include}"
"${qrpcbench_common_include}"

View File

@ -5,6 +5,7 @@
#include <qrpcbench_common.h>
#include <grpcpp/completion_queue.h>
#include <grpcpp/security/server_credentials.h>
#include <grpcpp/server.h>
#include <grpcpp/server_builder.h>
@ -21,7 +22,7 @@ class AsyncServer
public:
enum class State { Created, Running, Finished };
void run(std::string_view address = "0.0.0.0:0")
void run(std::string_view address = "0.0.0.0:0", bool enableSsl = false)
{
State expected = State::Created;
while (!mState.compare_exchange_weak(expected, State::Running)) {
@ -31,8 +32,21 @@ public:
{
grpc::ServerBuilder builder;
builder.AddListeningPort(address.data(), grpc::InsecureServerCredentials(),
&mSelectedPort);
std::shared_ptr<grpc::ServerCredentials> creds;
if (!enableSsl) {
std::cout << "Using InsecureServerCredentials\n";
creds = grpc::InsecureServerCredentials();
} else {
std::cout << "Using SslServerCredentials\n";
grpc::SslServerCredentialsOptions sslOpts;
sslOpts.pem_key_cert_pairs
.emplace_back(grpc::SslServerCredentialsOptions::PemKeyCertPair{
.private_key = { SslKey.data(), SslKey.size() },
.cert_chain = { SslCert.data(), SslCert.size() },
});
creds = grpc::SslServerCredentials(sslOpts);
}
builder.AddListeningPort({ address.data(), address.size() }, creds, &mSelectedPort);
builder.RegisterService(&mService);
mCompletionQueue = builder.AddCompletionQueue();
mAddressUri = address.substr(0, address.find_last_of(':'));
@ -71,9 +85,21 @@ private:
}
};
int main()
int main(int argc, char *argv[])
{
QStringList args;
for (int i = 0; i < argc; ++i)
args.push_back(argv[i]);
QCommandLineParser parser;
parser.setApplicationDescription("Asyncbenchserver");
parser.addHelpOption();
QCommandLineOption enableSsl("ssl", "Enable SSL");
parser.addOption(enableSsl);
parser.process(args);
absl::InitializeLog();
AsyncServer server;
server.run(HostUri);
server.run(HostUri, parser.isSet(enableSsl));
}

View File

@ -1,22 +1,33 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qrpcbench_common.h>
#include <proto/bench.grpc.pb.h>
#include <proto/bench.pb.h>
#include <qrpcbench_common.h>
#include <grpcpp/grpcpp.h>
#include <grpcpp/security/credentials.h>
#include <absl/log/initialize.h>
class AsyncGrpcClientBenchmark
{
public:
explicit AsyncGrpcClientBenchmark(uint64_t calls, size_t payload = 0) : mCalls(calls)
explicit AsyncGrpcClientBenchmark(uint64_t calls, size_t payload = 0, bool enableSsl = false)
: mCalls(calls)
{
if (payload > 0)
sData.assign(payload, 'x');
auto channel = grpc::CreateChannel(HostUri.data(), grpc::InsecureChannelCredentials());
std::shared_ptr<grpc::ChannelCredentials> creds;
if (enableSsl) {
grpc::SslCredentialsOptions sslOpts;
sslOpts.pem_root_certs = { SslRootKey.data(), SslRootKey.size() };
creds = grpc::SslCredentials(sslOpts);
} else {
creds = grpc::InsecureChannelCredentials();
}
auto channel = grpc::CreateChannel(HostUri.data(), creds);
mStub = qt::bench::BenchmarkService::NewStub(std::move(channel));
}

View File

@ -4,8 +4,12 @@
#include <proto/bench_client.grpc.qpb.h>
#include <qrpcbench_common.h>
#include <QtGrpc/qgrpcchanneloptions.h>
#include <QtGrpc/qgrpchttp2channel.h>
#include <QtNetwork/qsslcertificate.h>
#include <QtNetwork/qsslconfiguration.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qeventloop.h>
@ -18,13 +22,23 @@ class QtGrpcClientBenchmark : public QObject
{
Q_OBJECT
public:
explicit QtGrpcClientBenchmark(quint64 calls, qsizetype payload = 0) : mCalls(calls)
explicit QtGrpcClientBenchmark(quint64 calls, qsizetype payload = 0, bool enableSsl = false)
: mCalls(calls)
{
if (payload > 0)
sData = QByteArray(payload, 'x');
QUrl uri(QString("http://") + HostUri.data());
mClient.attachChannel(std::make_shared<QGrpcHttp2Channel>(std::move(uri)));
QGrpcChannelOptions opts;
if (enableSsl) {
QSslCertificate crt(QByteArray(SslRootKey.data(), SslRootKey.size()));
QSslConfiguration sslConfig;
sslConfig.setProtocol(QSsl::TlsV1_2OrLater);
sslConfig.addCaCertificate(crt);
sslConfig.setAllowedNextProtocols({ "h2" });
opts.setSslConfiguration(sslConfig);
}
mClient.attachChannel(std::make_shared<QGrpcHttp2Channel>(std::move(uri), opts));
}
~QtGrpcClientBenchmark() override = default;
@ -151,7 +165,7 @@ void QtGrpcClientBenchmark::clientStreaming()
quint64 recvBytes = 0;
const auto resp = stream->read<qt::bench::ClientStreamingResponse>();
if (resp->hasPayload())
recvBytes = static_cast<quint64>(resp->payload().size());
recvBytes = static_cast<quint64>(resp->payload().size());
Client::printRpcResult("ClientStreaming", mTimer.nsecsElapsed(),
counter, recvBytes, sendBytes);
} else {

View File

@ -17,6 +17,92 @@
static constexpr std::string_view HostUri = "localhost:65002";
// Valid for the next 100 years.
static constexpr std::string_view SslCert = R"(
-----BEGIN CERTIFICATE-----
MIID+jCCAuKgAwIBAgIUVJNsgxX2GVzFdU8yC0xwETtnHWwwDQYJKoZIhvcNAQEL
BQAwgZMxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIDAZCZXJsaW4xDzANBgNVBAcMBkJl
cmxpbjEcMBoGA1UECgwTVGhlIFF0IENvbXBhbnkgR21iSDEMMAoGA1UECwwDUiZE
MRIwEAYDVQQDDAlsb2NhbGhvc3QxIjAgBgkqhkiG9w0BCQEWE2Rlbm5pcy5vYmVy
c3RAcXQuaW8wIBcNMjUwMTE2MTU1ODIzWhgPMjEyNDEyMjMxNTU4MjNaMIGTMQsw
CQYDVQQGEwJERTEPMA0GA1UECAwGQmVybGluMQ8wDQYDVQQHDAZCZXJsaW4xHDAa
BgNVBAoME1RoZSBRdCBDb21wYW55IEdtYkgxDDAKBgNVBAsMA1ImRDESMBAGA1UE
AwwJbG9jYWxob3N0MSIwIAYJKoZIhvcNAQkBFhNkZW5uaXMub2JlcnN0QHF0Lmlv
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAszG9ps195LVF9kUDbQXj
1/5JAemlRvLMAJcr28virbqcCqphnode/vYGYiy2pbnPMJKxN9MsH5NMZH1/sn1A
PHGQ3sD6vcp24BZkgitDXLQab3QCF00K3Kka7GO6wQ9eloobBTtAWZDU/Px2LkLx
bmlIsr9Lbic2ZbKVWL3oRUECIAppmjEn1La+QSsV5lI2vROy6/b84OrBcYRDHifp
q70ZgIGO7AcucIeRAJGpfJJHxx8cuguDf0bgXJjsnIfXiAXCQkwtTWCrvES9akP4
dIJUz8onKAe7TRS1jaNGnXpikezhRa++GJNJhFAY3m6/0+qVHa0wByk5lxRoWV40
xwIDAQABo0IwQDAdBgNVHQ4EFgQUd2BWbXCVfYO0kHX+Ea5DcIzUlWIwHwYDVR0j
BBgwFoAU8jBTKqrkQqH2H7Kgyt6jtJtlZgcwDQYJKoZIhvcNAQELBQADggEBAG2f
xwaTuwBQ7ldk/8u4vfu1H8cq/eMLnmrbUm+QaSMdK1LXlhPQPpFcGN+6no/0tUA/
LhhzVzK6SRUgrm+IoGwL8ojyxdO760LgUOHN/VpvxQDY6DmBLct2L1sIRrjMNLym
ZgkXSmmeoswNgeonOwN8hIJz9Kx6xil1mPASGHvUaBFBdWDFxB/RuEYyv7X1wPeX
G2WqJZ+hoJESgtJFoybcbvqRGYq+ftXY8phacC1IuoaBinEBFxPrOkC2pzSHrvx2
Awm0fIbfSml23kefPh19Kquhf4NPdyUJo+RHuNn86tadANOEVVQ5slzaSuVu86Ym
u2A5Ea7yqvthhAzHrbg=
-----END CERTIFICATE-----
)";
static constexpr std::string_view SslKey = R"(
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCzMb2mzX3ktUX2
RQNtBePX/kkB6aVG8swAlyvby+KtupwKqmGeh17+9gZiLLaluc8wkrE30ywfk0xk
fX+yfUA8cZDewPq9ynbgFmSCK0NctBpvdAIXTQrcqRrsY7rBD16WihsFO0BZkNT8
/HYuQvFuaUiyv0tuJzZlspVYvehFQQIgCmmaMSfUtr5BKxXmUja9E7Lr9vzg6sFx
hEMeJ+mrvRmAgY7sBy5wh5EAkal8kkfHHxy6C4N/RuBcmOych9eIBcJCTC1NYKu8
RL1qQ/h0glTPyicoB7tNFLWNo0ademKR7OFFr74Yk0mEUBjebr/T6pUdrTAHKTmX
FGhZXjTHAgMBAAECggEAN5khTNXJT+LmmCiFjZgcP3IIWO2TeFXw8eX1l7bE2D5k
F/MRYsyBrv3KsT9KVFU4ccux7K46rHlZZHyD2G+ANMDPwC2EHsro41JPUQv3VJYU
9au60lv3GMvnLJ0s3qXUJUUoaREfQCrtyqjSSjw/CJDmG3+6+ax09kzYhbY2kPW7
RfIWZFTq9n5x3e7Zd2wPDD7PUiqZy3TIHFOwxtpSD3TapVismIFiRtLA6nV84gKf
zKCOLNqzU0usgfHiLBWGXxKcFVjXiv6Nss0o+TFbKhVPgh9r22tEkSFbLp19x2Ii
jF1DU1M5oR1ew9uF22IAQDl13xgwQ/qAHqtQssAR0QKBgQDoelgfUKeFndypiDct
zMtd9AxXAmDl4HSA01eUH9m6yXw5PS3mtK14eInJtywq+PwIvCeJz8IkaioG+JVi
x7xrACEcxjud6Yq8MkPpi8omFSlGBzL0VnZfJpEXUdwlYMiyy5viYLiFPBm8Z94x
Putiob227E1WEooaPMo77Hd4rQKBgQDFUz3bHU5R0tI4bBiM5WlBRsB1gfk/Sc10
WQi9D9d5uFfdFn2bXBzeBtWR8PYB9RO+SMc+i81Vva1IAk/7XbMLYXtoH2rrC6Fz
8OarQARhTGG5gfnAV48YD2AJGH4uCt1snVoJ/bxDz15vNSR0ywzfuURVgvSLXkPe
51PGXz6NwwKBgQDZZf+eWSgvVW6SwyUGmWrcU2puu3Stw3ZvOjO9+wL7H4whYsrX
4cIO1HnVvot5LBlUec9nmnds4jKnDjN0il/yl85fQClkBI+OalsDvYuujT9pkzXd
NDXBySkJa6247ocAXFNMITKstYVDoMYxuysXszTcKKIxiWjIHGzqGLmoiQKBgQC8
kQO3dJX3k2PZD1OWsVSYUKhyorYxSLHR0ZOMOKtNYmB0op197dSYSCenw4ET9cPc
P2hH2QlsOkpxWeRc7fm/knR/2CYwX3j2duu4EwEcigWJZS/qIsJX17mKd6F9Flzr
AqOckKFsm6o+06X3BmNTGJS4suBGntp1FNL16ua4SQKBgC0Y+822m1CjxLMtU6rr
5OH7MSHC7szyo+yiuch3APOOg1jxqjx5Ru1dohLvzU2vLmbFIWezxKmLwRYFjnoH
xhA6h48p0zvZRJlFjOyQCRAT4w3Hm938g9o81F+QNFWI44USsX/htdaPOxqR0SkP
UKzk7CPqzQYR2xHUi+VcBI93
-----END PRIVATE KEY-----
)";
static constexpr std::string_view SslRootKey = R"(
-----BEGIN CERTIFICATE-----
MIIECzCCAvOgAwIBAgIUBraeFSR5B//R/M22CKLtFNwf6XswDQYJKoZIhvcNAQEL
BQAwgZMxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIDAZCZXJsaW4xDzANBgNVBAcMBkJl
cmxpbjEcMBoGA1UECgwTVGhlIFF0IENvbXBhbnkgR21iSDEMMAoGA1UECwwDUiZE
MRIwEAYDVQQDDAlsb2NhbGhvc3QxIjAgBgkqhkiG9w0BCQEWE2Rlbm5pcy5vYmVy
c3RAcXQuaW8wIBcNMjUwMTE2MTU1ODIzWhgPMjEyNDEyMjMxNTU4MjNaMIGTMQsw
CQYDVQQGEwJERTEPMA0GA1UECAwGQmVybGluMQ8wDQYDVQQHDAZCZXJsaW4xHDAa
BgNVBAoME1RoZSBRdCBDb21wYW55IEdtYkgxDDAKBgNVBAsMA1ImRDESMBAGA1UE
AwwJbG9jYWxob3N0MSIwIAYJKoZIhvcNAQkBFhNkZW5uaXMub2JlcnN0QHF0Lmlv
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq2n9SNDLpd59+wV2AgOy
KYLMCcZE719w67cnYDAdFyBsVS5/Us2AiQtPYbESNDRX8SxOLM0b9FfTrFH3EU70
EIuClNqHq9OhtPoRoPo7bDULlEqOQeCFSMOrY2OW1m5ngvSqrY7LyVViH3QHk02g
afnkuCdTbAkNNfNyHWCkyVrad7RMk28t2dptSaH4SFripiaO2f59l8//lZ/6bdze
m2HhP5wcx88X02JdskmqcVuOOSlE03UoWGKG2O5TuRY0M48piypSuLz5Ajz72Erg
g3yFh98DKojW60EepM6Tgcq5l3UNlY4rzXBzCV2X+EO/VzvVKSc9u2k12cJmHZxh
lwIDAQABo1MwUTAdBgNVHQ4EFgQU8jBTKqrkQqH2H7Kgyt6jtJtlZgcwHwYDVR0j
BBgwFoAU8jBTKqrkQqH2H7Kgyt6jtJtlZgcwDwYDVR0TAQH/BAUwAwEB/zANBgkq
hkiG9w0BAQsFAAOCAQEARZWMphTnpwhUKS5/Z52MZOBTeqQgZ6vJ8SfRi1LIoDw/
tVrJQm1yLEvwZUY3NKGSOy6Rseuz68L6VOj9RHVc9xD5e8Si3gh/3Yyhjdv2g+1V
fJNaMEqvVA4sGnkXk21kbnloYaVpojyyBU5nBEivvFoSyYhlT3V+6gWqfFI6+F/o
FW9KC07WXcLcM41sQN7DsOx5q+6Qfc3VYl4z+k6X8rDEe3s1zFXZu2nPgYHD/New
9/h7mAQbil06MwuPOYbousc1uY95EVRLN4XrKHDkm3TxM8wHDipoanwyPnOqcpTy
Esh/Nj3INbL1yljh4Fi447mtfgg+ERh+BgAv61ZwsA==
-----END CERTIFICATE-----
)";
namespace Client {
template <typename T>
@ -47,15 +133,19 @@ inline void benchmarkMain(std::string_view name, int argc, char *argv[])
QCommandLineOption enableSStream("S", "Enable ServerStream");
QCommandLineOption enableCStream("C", "Enable ClientStream");
QCommandLineOption enableBStream("B", "Enable BiDiStream");
QCommandLineOption enableSsl("ssl", "Enable SSL");
parser.addOption(calls);
parser.addOption(payload);
parser.addOption(uniqueRpc);
parser.addOptions({
calls,
payload,
uniqueRpc,
parser.addOption(enableUnary);
parser.addOption(enableSStream);
parser.addOption(enableCStream);
parser.addOption(enableBStream);
enableUnary,
enableSStream,
enableCStream,
enableBStream,
enableSsl,
});
parser.process(args);
@ -63,42 +153,46 @@ inline void benchmarkMain(std::string_view name, int argc, char *argv[])
&& !parser.isSet(enableCStream) && !parser.isSet(enableBStream);
uint64_t amountCalls = parser.value(calls).toULong();
qsizetype payloadSize = parser.value(payload).toLong();
bool hasSsl = parser.isSet(enableSsl);
std::cout << std::format("#### Start of {} benchmark ####\n", name);
std::cout << std::format(" cpu-arch: {}\n", QSysInfo::buildCpuArchitecture().toStdString());
std::cout << std::format(" kernel: {}, {}\n", QSysInfo::kernelType().toStdString(),
QSysInfo::kernelVersion().toStdString());
std::cout << std::format(" host URI: {}\n\n", HostUri);
if (parser.isSet(payload))
std::cout << std::format(" Option: payload per message {} bytes\n", payloadSize);
if (parser.isSet(uniqueRpc))
std::cout << std::format(" Option: unique client per RPC {}\n", parser.isSet(uniqueRpc));
if (parser.isSet(payload) || parser.isSet(uniqueRpc))
if (parser.isSet(enableSsl))
std::cout << std::format(" Option: SSL communication\n");
if (parser.isSet(payload) || parser.isSet(uniqueRpc) || parser.isSet(enableSsl))
std::cout << "\n";
if (parser.isSet(uniqueRpc)) {
{
C client(amountCalls, payloadSize);
C client(amountCalls, payloadSize, hasSsl);
if (defaultRun || parser.isSet(enableUnary))
client.unaryCall();
}
{
C client(amountCalls, payloadSize);
C client(amountCalls, payloadSize, hasSsl);
if (defaultRun || parser.isSet(enableSStream))
client.serverStreaming();
}
{
C client(amountCalls, payloadSize);
C client(amountCalls, payloadSize, hasSsl);
if (defaultRun || parser.isSet(enableCStream))
client.clientStreaming();
}
{
C client(amountCalls, payloadSize);
C client(amountCalls, payloadSize, hasSsl);
if (defaultRun || parser.isSet(enableBStream))
client.bidiStreaming();
}
} else {
C client(amountCalls, payloadSize);
C client(amountCalls, payloadSize, hasSsl);
if (defaultRun || parser.isSet(enableUnary))
client.unaryCall();
if (defaultRun || parser.isSet(enableSStream))