Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
build*
*.cache
compile_commands.json
test_client.sh
test_server.sh
29 changes: 27 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,45 @@ project(qperf VERSION 1.0.0 LANGUAGES C)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# Set linker flags to use lld
if(DEFINED SANITIZE)
set(CMAKE_EXE_LINKER_FLAGS "-fuse-ld=lld")
set(CMAKE_MODULE_LINKER_FLAGS "-fuse-ld=lld")
set(CMAKE_SHARED_LINKER_FLAGS "-fuse-ld=lld")

# Set the sanitize options
set(SANITIZE_FLAGS
-fsanitize=address
-fsanitize=undefined
-fsanitize=signed-integer-overflow
-fsanitize=shift
-fsanitize=integer-divide-by-zero
-fsanitize=array-bounds
-fsanitize=implicit-conversion
-fsanitize=nullability
-fsanitize=integer
-fsanitize-address-use-after-return=always
-fsanitize-address-use-after-scope
)
set(BETTER_STACKTRACE -g -O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls)
endif()

add_subdirectory(extern)

add_executable(qperf main.c
client.h client.c
client_stream.h client_stream.c
server.h server.c
server_stream.h server_stream.c
common.h common.c)
common.h common.c
cpu-usage.h cpu-usage.c)

target_link_libraries(qperf PRIVATE quicly ev picotls)
target_link_libraries(qperf PRIVATE quicly ev picotls ${SANITIZE_FLAGS} ${BETTER_STACKTRACE})
target_compile_definitions(qperf PRIVATE QPERF_VERSION="${PROJECT_VERSION}")
target_compile_options(qperf PRIVATE
-Werror=implicit-function-declaration
-Werror=incompatible-pointer-types
-Werror=shift-count-overflow
${SANITIZE_FLAGS} ${BETTER_STACKTRACE}
)

95 changes: 53 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,56 +7,67 @@ Uses https://github.com/h2o/quicly
Usage: ./qperf [options]

Options:
-c target run as client and connect to target server
--cc [reno,cubic] congestion control algorithm to use (default reno)
-e measure time for connection establishment and first byte only
-g enable UDP generic segmentation offload
--iw initial-window initial window to use (default 10)
-l log-file file to log tls secrets
-p port to listen on/connect to (default 18080)
-s run as server
-t time (s) run for X seconds (default 10s)
-h print this help
-c target run as client and connect to target server
--cc [reno,cubic] congestion control algorithm to use (default reno)
-e measure time for connection establishment and first byte only
-g enable UDP generic segmentation offload
--iw initial-window initial window to use (default 10)
-l log-file file to log tls secrets
-p port to listen on/connect to (default 18080)
-s address listen as server on address
-t time (s) run for X seconds (default 10s)
-i num_instances number of instances to start (default nproc)
-h print this help
```

server

#### client
```
./qperf -s
starting server with pid 5624 on port 18080
got new connection
request received, sending data
connection 0 second 0 send window: 1112923 packets sent: 364792 packets lost: 373
connection 0 second 1 send window: 1238055 packets sent: 377515 packets lost: 123
connection 0 second 2 send window: 583352 packets sent: 355482 packets lost: 862
connection 0 second 3 send window: 275563 packets sent: 367538 packets lost: 607
connection 0 second 4 send window: 1100261 packets sent: 366005 packets lost: 20
connection 0 second 5 send window: 633010 packets sent: 356021 packets lost: 857
connection 0 second 6 send window: 1266610 packets sent: 367866 packets lost: 0
connection 0 second 7 send window: 1668530 packets sent: 360649 packets lost: 0
connection 0 second 8 send window: 1994930 packets sent: 364087 packets lost: 0
connection 0 second 9 send window: 1779683 packets sent: 374804 packets lost: 80
connection 0 total packets sent: 3654759 total packets lost: 2922
./qperf -c 2a01:4f8:1c1b:fd7a::1 -p 18000 -n 1
starting client with host 2a01:4f8:1c1b:fd7a::1, port 18000, runtime 10s, cc reno, iw 10
connection establishment time: 16ms
time to first byte: 16ms
second 0: 1.158 gbit/s, cpu 0: 21.65%
second 1: 1.161 gbit/s, cpu 2: 50.00%
second 2: 1.205 gbit/s, cpu 0: 32.29%
second 3: 1.162 gbit/s, cpu 2: 52.87%
second 4: 1.258 gbit/s, cpu 1: 34.04%
second 5: 1.387 gbit/s, cpu 1: 50.00%
second 6: 1.393 gbit/s, cpu 2: 15.96%
second 7: 1.366 gbit/s, cpu 0: 17.35%
second 8: 1.195 gbit/s, cpu 0: 46.67%
second 9: 1.226 gbit/s, cpu 1: 15.62%
connection closed
```
*Note*: The server looks for a TLS certificate and key in the current working dir named "server.crt" and "server.key" respectively([See TLS](#TLS)). You can use a self signed certificate; the client doesn't validate it.


client
#### server

```
./qperf -c 127.0.0.1
running client with host=127.0.0.1 and runtime=10s
connection establishment time: 6ms
time to first byte: 7ms
second 0: 3.144 gbit/s (422030372 bytes received)
second 1: 3.444 gbit/s (462189378 bytes received)
second 2: 3.184 gbit/s (427337822 bytes received)
second 3: 3.333 gbit/s (447304096 bytes received)
second 4: 2.996 gbit/s (402100242 bytes received)
second 5: 3.274 gbit/s (439462608 bytes received)
second 6: 3.083 gbit/s (413746021 bytes received)
second 7: 3.336 gbit/s (447686682 bytes received)
second 8: 3.034 gbit/s (407235597 bytes received)
second 9: 3.02 gbit/s (405314061 bytes received)
./qperf -s :: -p 18000
starting server with pid 15291,address ::, port 18000, cc reno, iw 10
starting server with pid 15293,address ::, port 18002, cc reno, iw 10
starting server with pid 15292,address ::, port 18001, cc reno, iw 10
starting server with pid 15294,address ::, port 18003, cc reno, iw 10
got new connection
request received, sending data
connection 0 second 0 send window: 622682 packets sent: 133403 packets lost: 2289, cpu 3: 1.99%
connection 0 second 1 send window: 716581 packets sent: 126095 packets lost: 23, cpu 3: 98.99%
connection 0 second 2 send window: 652943 packets sent: 131597 packets lost: 37, cpu 3: 97.98%
connection 0 second 3 send window: 563577 packets sent: 138904 packets lost: 35, cpu 3: 96.97%
connection 0 second 4 send window: 637191 packets sent: 127947 packets lost: 43, cpu 3: 100.00%
connection 0 second 5 send window: 727889 packets sent: 119218 packets lost: 13, cpu 3: 99.00%
connection 0 second 6 send window: 577401 packets sent: 111255 packets lost: 62, cpu 2: 53.33%
connection 0 second 7 send window: 807801 packets sent: 97623 packets lost: 0, cpu 2: 100.00%
connection 0 second 8 send window: 976761 packets sent: 92145 packets lost: 0, cpu 3: 53.54%
connection 0 second 9 send window: 890324 packets sent: 104484 packets lost: 11, cpu 3: 100.00%
transport close:code=0x0;frame=0;reason=
connection 0 second 10 send window: 891604 packets sent: 0 packets lost: 0, cpu 3: -nan%
connection 0 total packets sent: 1182671 total packets lost: 2513
connection closed
```
*Note*: The server looks for a TLS certificate and key in the current working dir named "server.crt" and "server.key" respectively([See TLS](#TLS)). You can use a self signed certificate; the client doesn't validate it.


# how to build
## 1. Install required dependencies
Expand Down
3 changes: 3 additions & 0 deletions client.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "client.h"
#include "client_stream.h"
#include "common.h"
#include "cpu-usage.h"

#include <ev.h>
#include <stdio.h>
Expand All @@ -13,6 +14,7 @@
#include <float.h>
#include <quicly/streambuf.h>


#include <picotls/../../t/util.h>

static int client_socket = -1;
Expand Down Expand Up @@ -125,6 +127,7 @@ int run_client(const char *port, bool gso, const char *logfile, const char *cc,
{
setup_session_cache(get_tlsctx());
quicly_amend_ptls_context(get_tlsctx());
getcpuusage();

client_ctx = quicly_spec_context;
client_ctx.tls = get_tlsctx();
Expand Down
17 changes: 16 additions & 1 deletion client_stream.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@

#define _GNU_SOURCE
#include "client_stream.h"
#include "client.h"
#include "common.h"
#include <ev.h>
#include <stdbool.h>
#include <quicly/streambuf.h>
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include "cpu-usage.h"



static int current_second = 0;
static uint64_t bytes_received = 0;
Expand All @@ -28,8 +36,15 @@ static void report_cb(EV_P_ ev_timer *w, int revents)
{
char size_str[100];
format_size(size_str, bytes_received);
double *percent = getcpuusage();

int cpu_core = sched_getcpu();
if (cpu_core == -1) {
perror("sched_getcpu");
exit(1);
}

printf("second %i: %s (%lu bytes received)\n", current_second, size_str, bytes_received);
printf("second %i: %s, cpu %d: %.2f%%\n", current_second, size_str, cpu_core, percent[cpu_core]);
fflush(stdout);
++current_second;
bytes_received = 0;
Expand Down
3 changes: 0 additions & 3 deletions common.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "common.h"

#include <sys/socket.h>
#include <netinet/udp.h>
#include <netdb.h>
Expand All @@ -22,8 +21,6 @@ struct addrinfo *get_address(const char *host, const char *port)
struct addrinfo hints;
struct addrinfo *result;

printf("resolving %s:%s\n", host, port);

memset(&hints, 0, sizeof(struct addrinfo));

hints.ai_family = AF_UNSPEC; // Let getaddrinfo decide if it's a hostname.
Expand Down
8 changes: 5 additions & 3 deletions common.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
#include <unistd.h>
#include <sys/syscall.h>

#define BREAKPOINT printf("%s() at %s:%d\n", __func__, __FILE__, __LINE__); __asm__("int3; nop" ::: "memory");

ptls_context_t *get_tlsctx();

struct addrinfo *get_address(const char *host, const char *port);
void enable_gso();
bool send_pending(quicly_context_t *ctx, int fd, quicly_conn_t *conn);
void print_escaped(const char *src, size_t len);


static inline int64_t min_int64(int64_t a, int64_t b)
{
if(a < b) {
Expand Down Expand Up @@ -44,7 +45,7 @@ static inline int64_t clamp_int64(int64_t val, int64_t min, int64_t max)

static inline uint64_t get_current_pid()
{
uint64_t pid;
uint64_t pid;

#ifdef __APPLE__
pthread_threadid_np(NULL, &pid);
Expand All @@ -53,4 +54,5 @@ static inline uint64_t get_current_pid()
#endif

return pid;
}
}

Loading