Hands-on TLS handshake lab: Python full HS p50 TLS1.3 1.51 ms vs TLS1.2 1.20 ms (~72× TCP); openssl resume ~1.5× / 4.1×. Localhost RSA numbers, no Docker.
5 min read
Every new HTTPS connection pays a TLS handshake before the first byte of app data. Session resume (tickets / IDs) is supposed to cut that cost. On a real WAN the 1-RTT story dominates; on localhost you mostly see crypto + userspace.
This is a hands-on lab with measured numbers:
ssl.wrap_socket full handshake p50 for TLS 1.3 vs TLS 1.2 vs plain TCP connect.openssl s_time -new vs -reuse connection rates on the same self-signed cert.session_reused stayed false.Related links:
Lab honesty (30 Sep 2026 IST): Shared Linux lab box (8 cores, kernel 6.12). Python 3.13.5, OpenSSL 3.5.7. Self-signed RSA-2048 CN=localhost. Loopback only. No Docker. No GPU. No API keys. Affiliates: 0.
Verdict up front: Python full HS TLS1.3 p50 = 1.51 ms, TLS1.2 = 1.20 ms, plain TCP 0.021 ms (~72× / ~57×). openssl s_time resume: TLS1.3 ~1.5×, TLS1.2 ~4.1× more conn/real-s than -new.
| Arm | Tool | What it measures |
|---|---|---|
| A | Python ssl | Full handshake wall p50 (n=50) |
| B | openssl s_time -new | Fresh handshakes / real second |
| C | openssl s_time -reuse | Session-resume handshakes / real second |
| Baseline | bare connect() | TCP-only connect p50 |
Related links:
| Setup | p50 ms | p95 ms | vs plain TCP |
|---|---|---|---|
| TLS 1.3 full | 1.507 | 2.948 | ~72× |
| TLS 1.2 full | 1.200 | 2.908 | ~57× |
| plain TCP connect | 0.021 | 0.055 | 1× |
On this localhost RSA stack, a full TLS handshake is tens of microseconds of TCP plus ~1.2–1.5 ms of crypto/userspace. TLS 1.2 edged TLS 1.3 here — that is a localhost RSA result, not a WAN 1-RTT claim.
| Version | Mode | Connections | Conn / real s | vs -new |
|---|---|---|---|---|
| TLS 1.3 | -new | 1852 | 617 | 1× |
| TLS 1.3 | -reuse | 2768 | 923 | ~1.49× |
| TLS 1.2 | -new | 2143 | 714 | 1× |
| TLS 1.2 | -reuse | 8840 | 2947 | ~4.13× |
Resume helped both versions. TLS 1.2 resume was the big win on this cert/stack (~4×). TLS 1.3 resume still ~1.5× over full — smaller relative gain when the full handshake is already cheaper in RTT terms on the wire (here we only see local CPU).
We tried passing SSLSession back into wrap_socket(..., session=...). session objects existed, but session_reused remained False for both TLS 1.2 and 1.3 on Python 3.13.5 / OpenSSL 3.5.7. Resume throughput numbers above are therefore openssl s_time -reuse only — labeled as such, not invented Python wins.
Related links:
session= resumes — it did not here; verify session_reused.session_reused, openssl s_time -reuse, or server metrics — do not assume.Localhost self-signed RSA-2048: Python full handshake p50 TLS1.3 = 1.51 ms, TLS1.2 = 1.20 ms, plain TCP 0.021 ms. openssl s_time resume boosted real conn/s by ~1.5× (TLS1.3) and ~4.1× (TLS1.2). Python session_reused did not flip true — resume evidence is openssl-only on this stack.
Evidence path on the lab box: lab-evidence/26-openssl-tls-handshake/results/. Affiliates: 0.
Lab evidence
Lab 30 Sep 2026 IST. Python 3.13.5 + OpenSSL 3.5.7. Self-signed RSA-2048 CN=localhost. Python wrap_socket full HS p50 (n=50): TLS1.3 1.507 ms; TLS1.2 1.200 ms; plain TCP connect 0.021 ms (~72× / ~57×). openssl s_time 3s wall real/s: TLS1.3 new 617.3 reuse 922.7 (~1.49×); TLS1.2 new 714.3 reuse 2946.7 (~4.13×). Python session_reused stayed False — resume from openssl -reuse only. No Docker. Affiliates: 0. Evidence: lab-evidence/26-openssl-tls-handshake/.
Hands-on itertools.islice vs list slice window lab: real ops/s taking ranges from sequences, measured on Linux localhost in this hands-on lab for SREs.
Lab1 Oct 20264 min read
Hands-on heapq.merge vs sorted(chain) multi-way merge: real records/s on pre-sorted lists, measured on Linux localhost today in this hands-on lab for SREs.
Lab1 Oct 20264 min read
Hands-on mmap MAP_SHARED write+msync vs pwrite region update: real MB/s with durability labels, measured on Linux localhost in this hands-on lab for SREs.
Lab1 Oct 20264 min read