Skip to content

Conversation

@Sashan
Copy link
Contributor

@Sashan Sashan commented Nov 5, 2025

This enables as to evaluate performance of OpenSSL QUIC stack against other QUIC implementations.

This enables as to evaluate performance of OpenSSL QUIC stack
against other QUIC implementations.
@Sashan Sashan moved this to Waiting Review in Development Board Nov 5, 2025
@Sashan
Copy link
Contributor Author

Sashan commented Nov 5, 2025

those changes were tested with tqclient/tqserver:

# git clone --recurse https://github.com/Tencent/tquic
# cd tquic
# cargo build --all # to build also tools/examples
# echo $?

if build is successful tqserver can be launched:

# cd target/debug/
# ./tquic_server -l 127.0.0.1:7070 -c path/to/servercert.pem -k path/to/serverkey.pem
# echo 'payload' > payload

Feel free to use servercert.pem and serverkey.pem found in $OPENSSL_SRCDIR/test/certs.
Command above starts QUIC server listening to port 7070. Use command here to connect:

# cd $PERFTOOLS./source/build
# ./ssl_poll_perf -m c -a 0 -c 100 -b 1 -u 0 http://127.0.0.1:7070/payload

command above launches client which performs 100 connections to tquic_server. Each connection
opens single bi-directional stream and fetches file payload.

to run tquic_client against ssl_poll_perf server, launch server first:

# cd $PERFTOOLS./source/build
# ./ssl_poll_perf -p 8080  -m s -a 0 path/to/servercert.pem path/to/serverkey.pem

To download 7 bytes from server above use URL http://127.0.0.1:8080/7 using
tquic_client command below:

./tquic_client \
    -t 1 \ # use one thread
    --max-concurrent-conns 100 \ # 100 concurrent connections
    --max-concurrent-requests 100 \ # 100 concurrent requests
    --max-requests-per-conn 1 \ # one request per connection
    --total-requests-per-thread 100 \ # 100 requests
    -d 0 # wait until all requests are completed
    -a http/0.9 # use http/0.9
    http://127.0.0.1:8080/7

@Sashan Sashan requested review from nhorman and quarckster and removed request for quarckster November 5, 2025 12:20
@quarckster
Copy link
Contributor

I'm wondering how to better run this in our performance benchmark lab. Is it enough to run both server and client on the same machine? Or the client and the server must be resided on separate hosts. In that case does it matter the platform of the counterpart? It will also bring questions of the simultaneous access to the counterpart from different testing machines. How will it affect on the results?

Copy link
Contributor

@jogme jogme left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First iteration

README.md Outdated
-w - the size of request body, the maximum size is 100MB. The default size is 64.
-p - port number to use
-t - terse output
-m - mode {client|server}, self-test mode when ommitted
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: mention somehow the one character option too (c,s)

time_t t;

t = time(&t);
ctime_r(&t, date_str);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: check on return code

}

static struct rr_buffer *
setup_response_0_9(struct rr_txt_full *rtf, unsigned int fsize)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need HTTP 0.9?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the tqserver/tqclient do not understand http/1.0. however the http/0.9 seems to be supported by various QUIC stack testing tools.

Though I'm not sure about keeping support for http/1.0 I'd like to keep for a while. I will drop it if I will not find a use case for it.

return NULL;

switch (alpn) {
case 0:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use the enum types here instead of magic numbers; other places also

break;
case RUN_MODE_CLIENT:
if (argv[optind] != NULL) {
url = argv[optind];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the parse_url can be done here and fail right away if the url is missing or incorrect

Comment on lines 3526 to 3528
free(hostname);
free(portstr);
free(request_path);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these should be freed on the error path too

Sashan and others added 4 commits November 6, 2025 09:52
Co-authored-by: Pocs Norbert <norbertpocs0@gmail.com>
Co-authored-by: Pocs Norbert <norbertpocs0@gmail.com>
Co-authored-by: Pocs Norbert <norbertpocs0@gmail.com>
Co-authored-by: Pocs Norbert <norbertpocs0@gmail.com>
@t8m
Copy link
Member

t8m commented Nov 6, 2025

I'm wondering how to better run this in our performance benchmark lab. Is it enough to run both server and client on the same machine? Or the client and the server must be resided on separate hosts. In that case does it matter the platform of the counterpart? It will also bring questions of the simultaneous access to the counterpart from different testing machines. How will it affect on the results?

IMO it SHOULD run on the same machine over loopback to avoid network latencies, etc.

@Sashan
Copy link
Contributor Author

Sashan commented Nov 6, 2025

I'm wondering how to better run this in our performance benchmark lab. Is it enough to run both server and client on the same machine? Or the client and the server must be resided on separate hosts. In that case does it matter the platform of the counterpart? It will also bring questions of the simultaneous access to the counterpart from different testing machines. How will it affect on the results?

this is should be sufficient:

lifty$ ./ssl_poll_perf -t /path/to/certs/servercert.pem /path/to/certs/serverkey.pem  
268.1150

The output is the time it took to establish 10 connections. each connection opens 10 bidirectional streams and 10 unidirectional stream pairs. each stream performs http/1.0 request to obtaub 64bytes. This is a default pre-set. We can either change defaults here:

3405     const char *ccountstr = "10";
3406     const char *bstreamstr = "10";
3407     const char *ustreamstr = "10";
3408     const char *rep_sizestr = "64";
3409     const char *req_sizestr = "64";

Or you can pass commandline options which control those settings. command below performs the same workload as ./ssl_poll_perf -t /path/to/certs//... comands

./ssl_poll_test -c 10 -b 10 -u 10 -w 64 -s 64 -t /path/to/certs/servercert.pem /path/to/certs/serverkey.pem  

Or are you asking how to cross test OpenSSL quic stack with other QUIC clients/servers?

@Sashan Sashan requested a review from jogme November 6, 2025 10:06
if (port_l != 0) {
free(portstr);
portstr = service;
service = NULL;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when no port is defined BIO_parse_hostserv fills service with u to me locally, strtol return 0 and the assert below on service fails. IMO moving this line outside the "if" should fix it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this case assert() does not hold and we are better to put OPENSSL_free() back for service. I think it's more sensible.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay, I have nothing against

case RUN_MODE_CLIENT:
if (argv[optind] != NULL)
parse_url(argv[optind]);
break;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should overflow when the above if is false

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case I prefer to restore what was there.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iirc that still does not correctly handle the case when there is no URL provided in the program args

@Sashan Sashan requested a review from jogme November 6, 2025 11:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Waiting Review

Development

Successfully merging this pull request may close these issues.

5 participants