Skip to content

perf: enable TCP_NODELAY on sockets - #4336

Merged
abonander merged 1 commit into
transact-rs:mainfrom
dmitryvk:opt-tcpnodelay
Aug 17, 2026
Merged

perf: enable TCP_NODELAY on sockets#4336
abonander merged 1 commit into
transact-rs:mainfrom
dmitryvk:opt-tcpnodelay

Conversation

@dmitryvk

@dmitryvk dmitryvk commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Setting TCP_NODELAY removes unnecessary delays when sending network packets, removing ~40ms delay in some cases.

Does your PR solve an issue?

Fixes #4335

Is this a breaking change?

No, not a breaking change. This only improves performance in some cases.

@abonander
abonander merged commit 6e57d05 into transact-rs:main Aug 17, 2026
147 checks passed
adriangb added a commit to adriangb/sqlx that referenced this pull request Aug 21, 2026
Correctness:

- Windows writes idle and interval together through `SIO_KEEPALIVE_VALS` and
  cannot leave one of them alone, so an unset one was being sent as 0 ms rather
  than left at the system default. Substitute libpq's own Windows values there
  (2h idle, 1s interval), as `pqSetKeepalivesWin32` does.
- Normalize the parameters in one place, `TcpKeepalive::normalized()`: zero
  means "system default", and fractional durations round up to whole seconds.
  `socket2` truncates, so a sub-second value reached `setsockopt()` as a literal
  0, which Linux rejects with `EINVAL`; only the URL parser normalized before,
  leaving both builders (and MySQL, which has no URL form) exposed.
- A value the kernel rejects now fails with `Error::Configuration` naming the
  parameters instead of a bare `Io(EINVAL)` that mentions neither.
- `?keepalives_idle=0` on its own left keepalive off, because 0 was folded to
  "unset" before deciding whether any parameter had been given. Any of the three
  now turns keepalive on, as in libpq.
- Negative values clamp to "system default" as libpq's `strtol` path does,
  rather than failing to parse.
- `build_url()` emits the keepalive parameters, so they survive `to_url_lossy()`
  alongside `sslmode` and `statement-cache-capacity`.
- Raise the workspace `tokio` floor to 1.27, the first release with
  `AsFd`/`AsSocket` on `TcpStream`, which `SockRef::from()` requires.

Docs:

- Correct the platform-support paragraph: `idle` is silently dropped on OpenBSD,
  Haiku and Vita, and `retries` fails the connection rather than being ignored
  where `TCP_KEEPCNT` is missing.
- List the four URL parameters in the `PgConnectOptions` table with a note on
  the semantics, and say on the MySQL side that no URL form exists.
- Cite transact-rs#4336 for `TCP_NODELAY` rather than transact-rs#3055, which was reverted by transact-rs#4022.
- Correct the socket2 dependency comment: `tokio` only bundles socket2 0.6 from
  1.47 onwards.

Tests:

- Exercise the `setsockopt()` path on a loopback socket, reading the values back
  and covering the zero, sub-second and kernel-rejected cases. Only the builder
  and URL parsing were covered before, so none of the above was observable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@nbari

nbari commented Sep 2, 2026

Copy link
Copy Markdown

Hi @dmitryvk, many thanks for the fix; this looks more like a regression, currently with the latest version:

image

But the fix makes it behave like before; I caught this while testing with (https://github.com/nbari/dbpulse/)

@abonander any idea when this will be released?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Missing TCP_NODELAY on TCP sockets

3 participants