{"id":22220725,"url":"https://github.com/giovannibaccichet/dncs-http3","last_synced_at":"2025-07-27T15:33:14.252Z","repository":{"id":68910523,"uuid":"323053122","full_name":"GiovanniBaccichet/DNCS-HTTP3","owner":"GiovanniBaccichet","description":"Docker-based virtualized framework for analysing HTTP/3+QUIC performance and compare it to HTTP/2 and TCP.","archived":false,"fork":false,"pushed_at":"2021-02-18T19:17:45.000Z","size":37397,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-02-13T21:52:43.005Z","etag":null,"topics":["docker","evaluation-framework","http3","performace","performance-evaluation","quic","ssl","tcp","vagrant","video-streaming"],"latest_commit_sha":null,"homepage":"https://hub.docker.com/u/giovannibaccichet","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GiovanniBaccichet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2020-12-20T11:12:33.000Z","updated_at":"2024-02-13T21:52:48.084Z","dependencies_parsed_at":"2024-02-13T21:52:47.936Z","dependency_job_id":"b6e5bf20-70b3-4141-92ff-baeb15ea930a","html_url":"https://github.com/GiovanniBaccichet/DNCS-HTTP3","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GiovanniBaccichet%2FDNCS-HTTP3","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GiovanniBaccichet%2FDNCS-HTTP3/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GiovanniBaccichet%2FDNCS-HTTP3/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GiovanniBaccichet%2FDNCS-HTTP3/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GiovanniBaccichet","download_url":"https://codeload.github.com/GiovanniBaccichet/DNCS-HTTP3/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227817170,"owners_count":17824199,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","evaluation-framework","http3","performace","performance-evaluation","quic","ssl","tcp","vagrant","video-streaming"],"created_at":"2024-12-02T23:09:42.845Z","updated_at":"2024-12-02T23:09:43.388Z","avatar_url":"https://github.com/GiovanniBaccichet.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- PROJECT LOGO --\u003e\n\u003cbr /\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/GiovanniBaccichet/DNCS-HTTP3\"\u003e\n    \u003cimg src=\"media/isometric-laptop.png\" alt=\"Logo\" width=\"210\"\u003e \n  \u003c/a\u003e\n\n  \u003ch3 align=\"center\"\u003ePerformance Evaluation of HTTP/3 w/ QUIC\u003c/h3\u003e\n\n  \u003cp align=\"center\"\u003e\n    Design of Network and Communication Systems - University of Trento - prof. Fabrizio Granelli\n    \u003cbr /\u003e\n    \u003ca href=\"https://github.com/GiovanniBaccichet/DNCS-HTTP3/blob/main/media/Presentation%20DNCS%20Lab.pdf\"\u003e\u003cstrong\u003eDownload presentation »\u003c/strong\u003e\u003c/a\u003e\n    \u003cbr /\u003e\n    \u003cbr /\u003e\n    \u003ca href=\"https://github.com/GiovanniBaccichet\"\u003eGiovanni Baccichet\u003c/a\u003e\n    |\n    \u003ca href=\"https://github.com/davideparpinello\"\u003eDavide Parpinello\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n\u003c!-- TABLE OF CONTENTS --\u003e\n\u003cdetails open=\"open\"\u003e\n  \u003csummary\u003e\u003ch2 style=\"display: inline-block\"\u003eTable of Contents\u003c/h2\u003e\u003c/summary\u003e\n  \u003col\u003e\n    \u003cli\u003e\n      \u003ca href=\"#about-\"\u003eAbout 🔍\u003c/a\u003e\n      \u003cul\u003e\n        \u003cli\u003e\u003ca href=\"#team\"\u003eTeam\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#project\"\u003eProject\u003c/a\u003e\u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/li\u003e\n    \u003cli\u003e\n      \u003ca href=\"#lab-environment-\"\u003eLab Environment 🌍\u003c/a\u003e\n    \u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#vagrant-configuration-\"\u003eVagrant Configuration 🖥\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#docker-configuration-\"\u003eDocker Configuration 🐳\u003c/a\u003e\n    \u003cul\u003e\n        \u003cli\u003e\u003ca href=\"#ssl-certificates\"\u003eSSL Certificates\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#web-page---image\"\u003eWeb Page - image\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#video-streaming---image\"\u003eVideo Streaming - image\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#deployment\"\u003eDeployment\u003c/a\u003e\u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#performance-evaluation-\"\u003ePerformance Evaluation ⏱\u003c/a\u003e\u003c/li\u003e\n    \u003cul\u003e\n        \u003cli\u003e\u003ca href=\"#evaluation-criteria\"\u003eEvaluation Criteria\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#results\"\u003eResults\u003c/a\u003e\u003c/li\u003e\n    \u003c/ul\u003e\n    \u003cli\u003e\n      \u003ca href=\"#conclusions-\"\u003eConclusions 💡\u003c/a\u003e\n    \u003c/li\u003e\n    \u003cli\u003e\n      \u003ca href=\"#credits-\"\u003eCredits 📓\u003c/a\u003e\n    \u003c/li\u003e\n  \u003c/ol\u003e\n\u003c/details\u003e\n\n\u003c!-- ABOUT THE PROJECT --\u003e\n\n## About 🔍\n\n### Team\n\nTeam members are **Baccichet Giovanni** (`202869`) and **Parpinello Davide** (`201494`).\n\n### Project\n\nThe goal of the project is to build a virtualized framework for analyzing the performance of HTTP/3 + QUIC, with respect to HTTP/2 or TCP.\n\n**Suggested software**: Vagrant, OpenVSwitch, docker, or alternatively mininet+docker (Comnetsemu)\n**Reference software**: https://blog.cloudflare.com/experiment-with-http-3-using-nginx-and-quiche/\n\n## Lab Environment 🌍\n\nIn order to be as unbiased as possibile, and also to make the performance evaluation replicable by everyone, it is necessary a virtualized lab. More specifically, in the implementation chosen, two softwares are used to set up the environment: **Docker** and **Vagrant**.\nIn order to replicate a realistic scenario, the setup will be the following: one host, used as a client is connected directly to the only router of the lab. Than there are 2 hosts used as servers and belonging to the same subnet (different from the client one) connected to a switch and so to the router. The fist host will be named `client`, and on top of it will run the software needed for the performance evaluation (that will be discussed in a dedicated section). On the other hand, the second host will be called `web-server` and will run 3 different Docker containers and similarly the last one will be called `video-server` and it will run the remaining 3 containers.\n\n\u003cimg src=\"media/Network-topology.png\" width=\"1000\"\u003e\n\nFor the performance evaluation to be likely realistic, it would have to include both web-page static contents and also video streaming (the most popular medium nowadays). Hence the need of 6 different Docker containers: `(3 protocols to be tested) X (2 kinds of media)`. The containers could run on top the same host, but for the HTTP/3+QUIC container to work, it needs to use port `80` and `443`, and since there are 2 of those, it would be a problem. For this specific reason the containers are divided in 2 different hosts (one dedicated to web static contents, and the other dedicated to video streaming).\n\n| Service         | Protocol      | IP address  | Ports   |\n| --------------- | ------------- | ----------- | ------- |\n| Web page        | TCP           | 192.168.2.2 | 82, 452 |\n| Web page        | HTTP/2        | 192.168.2.2 | 81, 451 |\n| Web page        | HTTP/3 + QUIC | 192.168.2.2 | 80, 443 |\n| Video streaming | TCP           | 192.168.2.3 | 82, 452 |\n| Video streaming | HTTP/2        | 192.168.2.3 | 81, 451 |\n| Video streaming | HTTP/3 + QUIC | 192.168.2.3 | 80, 443 |\n\nRegarding the IP addresses assigned by Vagrant to the different hosts, they are the following: `router::eth1` is `192.168.1.1`, `router::eth2` is `192.168.2.1`, `client::eth1` is `192.168.1.2` and `web-server::eth1` is `192.168.2.2` and `video-server::eth1` is `192.168.2.3`.\n\n## Vagrant Configuration 🖥\n\nAs showcased earlier, Vagrant is used to manage the VM and networking side of the Lab environment. The imaged used for the OS is `ubuntu/bionic64`.\nSome things have to be pointed out: the X11 server is forwarded in order to use performance evaluation tools and browsers form the `client` (it will be necessary for the host machine to run an X-server, like XQuartz for macOS). This is achieved by adding in the Vagrantfile the following lines:\n\n```Ruby\n  config.ssh.forward_agent = true\n  config.ssh.forward_x11 = true\n```\n\nAlso, both the `client` and the `server` have 1024 MB of RAM in order to be capable of running Google Chrome (the first) and ffmpeg (the last).\nAll the provisioning scripts are in the `vagrant` folder and are used mainly for routing and the installation of basic software.\nThe provisioning script responsible for the Docker deployment (`docker_run.sh`) is also contained in the same folder as the others, but will be discussed later on.\nLast but not least, it is important to know that docker images won't be compiled at each `vagrant up`, but instead downloaded from the [Docker Hub](https://hub.docker.com/u/giovannibaccichet) (which automatically builds them every time something is committed to this repository), in order to save time.\n\n## Docker Configuration 🐳\n\nThe approach chosen was to build 2 different Docker images, deploying 6 containers: the first one serves the purpose of running a web-server, whereas the last one is used to stream HLS video. The video-streaming image is a mod of the web-server one and they are both based on NGINX server, more specifically NGINX 1.16.1 (this particular version is needed to run the quiche-patch). In fact both images are pre-configured as HTTP/3 capable, but will be limited in the `nginx.conf` configuration file to run on TCP, HTTP/2 and HTTP/3+QUIC as demanded (in order to complete the performance evaluation).\n\n### SSL Certificates\n\nSince QUIC needs encryption in order to work properly, SSL/TLS certificates had to be generated. After a little bit of research, it turned out that self-signed SSL certificates cannot be used with QUIC: only trusted SSL certificates issued by a CA work.\nLet's Encrypt can be used to generate valid certificated, associated with a real domain. Using certbot and DNS verification, the command is the following:\n\n```bash\nsudo certbot -d HOSTNAME --manual --preferred-challenges dns certonly\n```\n\nAnd the files needed for NGINX can be found in `/etc/letsencrypt/live/HOSTNAME`.\nIt is useful to create a subdomain redirecting to `192.168.2.2` (in this case **web.bacci.dev**) or `192.168.2.3` (in this case **video.bacci.dev**) associated with said certificates. This is necessary to connect to the docker containers from the `client` inside the Vagrant environment because as highlighted earlier QUIC accepts only encrypted traffic.\nFor obvious reasons the certificates used in this performance evaluation are not included in the package, however they can be generated with ease using the command above and passed to docker using the `-v` option (this will be explained in the Deployment section).\n\n### Web Page - image\n\nThe web-server image is built form the `Dockerfile_TEXT` that can be found in the `docker` folder. The Linux distro used as subsystem is Ubuntu. After installing all the dependencies and NGINX, the latter is patched using [Cloudflare's quiche patch](https://github.com/cloudflare/quiche).\nAs reported earlier, the base-image is HTTP/3 capable, but the web-server can run on TCP, HTTP/2 or HTTP/3 as demanded, using the configuration file, passed by the `-v` option in Docker (this will be discussed in the Deployment section). Here's an example of said file:\n\n```Properties\nevents {\n    worker_connections 1024;\n}\n\nhttp {\n    server {\n        # https://github.com/cloudflare/quiche/tree/master/extras/nginx\n        # Enable QUIC and HTTP/3.\n        listen 443 quic reuseport;\n\n        # Enable HTTP/2 (optional).\n        listen 443 ssl http2;\n\n        server_name web.bacci.dev;\n\n        # Certificates generated for localhost.bacci.dev\n        ssl_certificate certs/fullchain.pem;\n        ssl_certificate_key certs/privkey.pem;\n\n        # Enable all TLS versions (TLSv1.3 is required for QUIC).\n        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;\n        ssl_early_data on;\n\n\n        # Request buffering in not currently supported for HTTP/3.\n        proxy_request_buffering off;\n\n        # Add Alt-Svc header to negotiate HTTP/3.\n        add_header alt-svc 'h3-27=\":443\"; ma=86400';\n\n        location / {\n            root html;\n            index index.html index.htm;\n        }\n    }\n}\n```\n\nNGINX configuration files can be found in the `docker/confs` folder, named after their function: `PROTOCOL.TYPE.nginx.conf`.\n\n### Video Streaming - image\n\nAs outlined above, in order to do a comprehensive performance evaluation of HTTP/3 in a realistic scenario, it was necessary to analyze also its video streaming capabilities.\nThe streaming protocol of choice was HLS because of its large diffusion and for its performance. At first, HLS was exclusive to iPhones, but today almost every device supports this protocol, so it has become a proprietary format. As the name implies, HLS delivers content via standard HTTP web servers. This means that no special infrastructure is needed to deliver HLS content. Any standard web server or CDN will work. Additionally, content is less likely to be blocked by firewalls with this protocol, which is a plus. HLS can play video encoded with the H.264 or HEVC/H.265 codecs.\nThe video streaming Docker image is just a mod of the one created in the previous section. The only difference is an **RTMP** plugin for NGINX and the installation of **ffmpeg** (used for encoding the video file and looping it, simulating a live streaming). The information necessary to be able to do this mod can be found [here](https://www.nginx.com/blog/video-streaming-for-remote-learning-with-nginx/).\nIt follows an example of the NGINX's configuration file for the video streaming image:\n\n```Properties\n#worker_processes  auto;\nevents {\n    worker_connections 1024;\n}\n\n# RTMP configuration\nrtmp {\n    server {\n        listen 1935; # Listen on standard RTMP port\n        chunk_size 4000;\n\n        application show {\n            live on;\n            # Turn on HLS\n            hls on;\n            hls_path /mnt/hls/;\n            hls_fragment 3;\n            hls_playlist_length 60;\n            # Disable consuming the stream from nginx as rtmp\n            deny play all;\n        }\n    }\n}\n\nhttp {\n    server {\n        listen 443 quic reuseport;\n\n        listen 443 ssl http2;\n\n        server_name video.bacci.dev;\n\n        ssl_certificate certs/fullchain.pem;\n        ssl_certificate_key certs/privkey.pem;\n\n        # Enable all TLS versions (TLSv1.3 is required for QUIC).\n        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;\n        ssl_early_data on;\n\n\n        # Request buffering in not currently supported for HTTP/3.\n        proxy_request_buffering off;\n        add_header alt-svc 'h3-27=\":443\"; ma=86400';\n\n        location / {\n            # Disable cache\n            add_header 'Cache-Control' 'no-cache';\n\n            # CORS setup\n            add_header 'Access-Control-Allow-Origin' '*' always;\n            add_header 'Access-Control-Expose-Headers' 'Content-Length';\n\n            types {\n                # Application/dash+xml mpd;\n                application/vnd.apple.mpegurl m3u8;\n                video/mp2t ts;\n            }\n            root /mnt;\n        }\n    }\n}\n```\n\nSimilarly to the first Docker image, also the later has different configuration files, in order to run on different protocols. Said files are also contained in the `docker/confs` folder.\n\n### Deployment\n\nFor the deployment part, it is necessary to launch the Lab Environment discussed earlier with the command `vagrant up`. The latest builded Docker images will be downloaded from the [Docker Hub](https://hub.docker.com/u/giovannibaccichet) and deployed automatically.\n\nSome notes have to be made: in order to change the port configuration used and the SSL/TLS certificates needed, depending on the chosen method of deployment, `docker/docker_deploy.sh` or `vagrant/docker_run.sh` have to be modified.\nAll ports are parameterized (except HTTP/3 ones, because otherwise it won't work), so the configuration is pretty straight forward:\n\n```bash\n# DOCKER RUN PORT SETTINGS\necho \"+--------------------------------------------------------+\"\necho \"|                      PORT SETTINGS                     |\"\necho \"+--------------------------------------------------------+\"\n\n# SET PORTS\n# TCP text/video\nh1TEXTp1=82\nh1TEXTp2=452\n# HTTP/2 text/video\nh2TEXTp1=81\nh2TEXTp2=451\n```\n\nWhile for using custom generated SSL/TLS certificates, it is necessary to change the path to the needed certificates in `web-docker_run.sh` and `video-docker_run.sh`.\n\n```bash\nsudo docker run --name tcp-web -d -p $h1WEBp1:80 -p $h1WEBp2:443/tcp -p $h1WEBp2:443/udp -v $vagrantPath/confs/tcp.web.nginx.conf:/etc/nginx/nginx.conf -v $vagrantPath/certs/web/:/etc/nginx/certs/ giovannibaccichet/quiche-web\n```\n\nAlternatively it is necessary to clone the repo and replicate the following folder tree (replacing `fullchain.pem` and `privkey.pem` with the respective custom certificates):\n\n```\n.\n└── DNCS-HTTP3/\n    └── docker/\n        └── certs/\n            ├── video/\n            │   ├── fullchain.pem\n            │   └── privkey.pem\n            └── web/\n                ├── fullchain.pem\n                └── privkey.pem\n```\n\n## Performance Evaluation ⏱\n\nThe whole performance evaluation was done using the latest stable version of **Google Chrome** (`v 88.0.4324.150`) from the `client`, with the help of [httpstat](https://github.com/reorx/httpstat) for ease of use and visualization. In order to enable HTTP/3 and QUIC the application has to be launched with the following command:\n\n```bash\ngoogle-chrome --enable-quic --quic-version=h3-27\n```\n\nThe HTTP/3 version used was 27 and not 29 because of Google Chrome possible compatibility issues (the setting can be changed modifying the files in `docker/confs` folder).\nFor the web-page static content performance evaluation a reliable tool can be Google Chromes's **DevTool**, while for some streaming statistics were used online players with data (that will be discussed below).\n\n### Evaluation Criteria\n\nTwo different evaluation methodologies were applied to the web-static content and the video streaming.\nThe performance metrics used for the first one are:\n\n-   **TTFB** (_Time To First Byte_): it measures the duration from the user or client making an HTTP request to the first byte of the page being received by the client's browser. This time is made up of the socket connection time, the time taken to send the HTTP request, and the time taken to get the first byte of the page;\n-   **Page weight**: total weight of a single page assets, including HTML, CSS, JS, images, etc. (obviously independent from the infrastructure used);\n-   **Load Time**;\n-   **Number of requests**: how many times that the browser has to request assets and resources in order to complete the loading of the requested page;\n-   **TCP connection time**;\n-   **TLS handshake time**;\n-   **Server processing time**;\n-   **Content transfer time**.\n\nWhereas the performance metrics used for the latter are:\n\n-   **Startup time**: total delay between a viewer pushing “play” and the first frame.;\n-   **Latency**;\n-   **Bitrate**;\n-   **Dropped frames**;\n-   **Resource download events**: segment download duration expressed in milliseconds.\n\nThe video streaming performance evaluation was done using [this](https://hls-js.netlify.app/demo/) tool, letting the stream play for 90 seconds, than pausing it and exporting the data. The **startup time** metric has been obtained using [this](https://demo.theoplayer.com/test-your-stream-with-statistics) other player.\n\n### Results\n\n#### Web page performance\n\nIn order to have a brief overview of what has to be expected, **httpstat**'s output is very useful.\n\n**HTTP/3 + QUIC web page**:\n\n```bash\nvagrant@client:~$ httpstat https://web.bacci.dev:443\nConnected to 192.168.2.2:443 from 192.168.1.2:60864\n\nHTTP/2 200\nserver: nginx/1.16.1\ncontent-type: text/html\ncontent-length: 106200\netag: \"60251560-19ed8\"\nalt-svc: h3-27=\":443\"; ma=86400\naccept-ranges: bytes\n\nBody stored in: /tmp/tmp1G1tZP\n\n  DNS Lookup   TCP Connection   TLS Handshake   Server Processing   Content Transfer\n[     4ms    |       2ms      |     17ms      |        2ms        |        8ms       ]\n             |                |               |                   |                  |\n    namelookup:4ms            |               |                   |                  |\n                        connect:6ms           |                   |                  |\n                                    pretransfer:23ms              |                  |\n                                                      starttransfer:25ms             |\n                                                                                 total:33ms\n```\n\nTo be noticed that in this case the request is `h3-27` but the response is HTTP/2; it is not that important since all the metrics will be re-analyzed later with Google Chrome's developer tools (using HTTP/3).\n\n**HTTP/2 + SSL web page**:\n\n```bash\nvagrant@client:~$ httpstat https://web.bacci.dev:451\nConnected to 192.168.2.2:451 from 192.168.1.2:43398\n\nHTTP/2 200\nserver: nginx/1.16.1\ncontent-type: text/html\ncontent-length: 106200\netag: \"60251560-19ed8\"\naccept-ranges: bytes\n\nBody stored in: /tmp/tmp7A0ND6\n\n  DNS Lookup   TCP Connection   TLS Handshake   Server Processing   Content Transfer\n[     4ms    |       1ms      |     14ms      |        3ms        |        6ms       ]\n             |                |               |                   |                  |\n    namelookup:4ms            |               |                   |                  |\n                        connect:5ms           |                   |                  |\n                                    pretransfer:19ms              |                  |\n                                                      starttransfer:22ms             |\n                                                                                 total:28ms\n```\n\n**TCP + SSL web page**:\n\n```bash\nvagrant@client:~$ httpstat https://web.bacci.dev:452\nConnected to 192.168.2.2:452 from 192.168.1.2:32988\n\nHTTP/1.1 200 OK\nServer: nginx/1.16.1\nContent-Type: text/html\nContent-Length: 106200\nConnection: keep-alive\nETag: \"60251560-19ed8\"\nAccept-Ranges: bytes\n\nBody stored in: /tmp/tmphG9UJe\n\n  DNS Lookup   TCP Connection   TLS Handshake   Server Processing   Content Transfer\n[     4ms    |       2ms      |     14ms      |        3ms        |        3ms       ]\n             |                |               |                   |                  |\n    namelookup:4ms            |               |                   |                  |\n                        connect:6ms           |                   |                  |\n                                    pretransfer:20ms              |                  |\n                                                      starttransfer:23ms             |\n                                                                                 total:26ms\n```\n\nBelow is a summary table for the metrics acquired with Google Chrome:\n\n| Protocol      | Page weight | TTFB      | Load time | # requests | # tcp connections |\n| ------------- | ----------- | --------- | --------- | ---------- | ----------------- |\n| HTTP/3 + QUIC | 3.5 MB      | 2.83 msec | 1.08 sec  | 30         | 0                 |\n| HTTP/2        | 3.5 MB      | 3.21 msec | 961 msec  | 30         | 1                 |\n| TCP           | 3.5 MB      | 2.16 msec | 899 msec  | 30         | 6                 |\n\nAll the data has been acquired through Google Chrome DevTools (from the `client`), as shown in the screenshots below.\n\n**HTTP/3 + QUIC web page**:\n\n\u003cimg src=\"media/screenshots/DevTools-h3.png\" width=\"1000\"\u003e\n\n**HTTP/2 + SSL web page**:\n\n\u003cimg src=\"media/screenshots/DevTools-h2.png\" width=\"1000\"\u003e\n\n**TCP + SSL web page**:\n\n\u003cimg src=\"media/screenshots/DevTools-h1.png\" width=\"1000\"\u003e\n\n_(The number of TCP connection established can be noticed in the Connection ID column)_\n\nAs expected by the **httpstat** output, TCP was faster, followed by HTTP/2 and then HTTP/3.\nOne of the main touted advantages of HTTP/3 is increased performance, specifically around fetching multiple objects simultaneously, and it can be seen in the waterfall above.\nRunning other tests on **heavier web content**, the results didn't change much:\n\n| Protocol      | Page weight | TTFB      | Load time | # requests | # tcp connections |\n| ------------- | ----------- | --------- | --------- | ---------- | ----------------- |\n| HTTP/3 + QUIC | 7.3 MB      | 5.51 msec | 3.33 sec  | 134        | 0                 |\n| HTTP/2        | 7.3 MB      | 5.63 msec | 2.99 sec  | 123        | 1                 |\n| TCP           | 7.3 MB      | 4.64 msec | 2.92 sec  | 120        | 6                 |\n\nScreenshots relative to the above table can be found in the `media/screenshots` folder.\n\n### Video streaming performance\n\nIn order to be as unbiased as possible all the tests were done using the same machine, without using it (so every server was in the same condition of CPU \u0026 RAM usage).\n\nBelow the player used for the metrics and than the player used for the **startup time** calculation.\n\n\u003cimg src=\"media/screenshots/hls.js-demo.png\" width=\"1000\"\u003e\n\n\u003cimg src=\"media/screenshots/theoplayer.png\" width=\"1000\"\u003e\n\n| Protocol      | Startup time | Avg latency | Avg bitrate | Dropped frames |\n| ------------- | ------------ | ----------- | ----------- | -------------- |\n| HTTP/3 + QUIC | 1242 msec    | 46.39 msec  | 64.17 MB/s  | 328            |\n| HTTP/2        | 985 msec     | 27.86 msec  | 139.57 MB/s | 256            |\n| TCP           | 799 msec     | 25.78 msec  | 57.44 MB/s  | 603            |\n\n## Conclusions 💡\n\nIn conclusion, based on the performance evaluation, done with the same configuration and using pages of different sizes of web-pages (3.5 MB and 7.3 MB) and some HLS streams, it’s clear that **HTTP/3 is slower than HTTP/2**. Little increases in the performance are shown with very lightweight pages, but that scenario is unlikely to happen in the real world, where web pages weigh about 2/3 MB. Thanks to the parallel loading of resources and using the UDP protocol, it’s possible to see some improvements in congested environments like a real Internet scenario. Maybe, due to the development status of the HTTP/3 protocol, which still has not a stable release, significant improvements will come in the future with new features as congestion tuning or prioritization.\n\nThere's something else, performance aside, that's really exciting about HTTP/3: **fixing a decades old layering violation** that has made truly mobile internet impossible. In TCP, a connection is uniquely identified by the following tuple: `(src ip, src port, dst ip, dst port)`. The issue is that the user depends not only on layer 4 details (port numbers) but also on layer 3 information (IP addresses). This means we can not ever keep a connection alive when moving from one network and hence IP address into another. We can do some trickery to let people keep their addresses while inside of a network, but switch from mobile data to Wi-Fi and every TCP connection drops.\nThis is easy enough to solve, in theory. Give every connection an unique ID, and then remember the last address you received a packet for that connection from, ideally in the kernel. This makes IP addresses completely transparent to applications, just like MAC addresses are. However, the tuple is assumed almost everywhere and **NAT makes new layer 4 protocols impossible**. Unless you layer them over UDP. And this is exactly what Wireguard, QUIC, Mosh and others do.\n\n## Credits 📓\n\nThe website used for the web-static contents performance evaluation was made using [Froala Design Blocks](https://github.com/froala/design-blocks), in order to get an easy to make, good looking and realistic web page to analyze.\n\nThe video streamed using **ffmpeg** in the video server is named Big Buck Bunny and it is a 2008 libre movie project by the [Blender Foundation](https://www.blender.org/foundation/) the Creative Commons Attribution 3.0 license. In this specific case, the file in the `media` folder has been cut and compressed in order to save space.\n\n```\n(c) copyright 2008, Blender Foundation / www.bigbuckbunny.org\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgiovannibaccichet%2Fdncs-http3","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgiovannibaccichet%2Fdncs-http3","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgiovannibaccichet%2Fdncs-http3/lists"}