Для разбора задержки curl выведите time_namelookup, time_connect, time_appconnect, time_starttransfer и time_total. Это отметки времени от начала запроса, а не длительности пяти независимых этапов. Вычитайте соседние значения и проверяйте редиректы, протокол, IP и повторное использование соединения.

curl -w быстро отвечает, где выросла задержка: до TCP, на TLS, до первого байта или при передаче тела. Но строка «TLS 0,09 с, первый байт 0,14 с» не означает, что сервер думал 0,14 с: это накопленные отметки. Ошибка интерпретации ведёт к бессмысленной настройке PHP, когда время ушло в сеть или DNS. Ниже — рабочий формат, реальные замеры с одного сервера и границы вывода.
Снимите пять временных отметок одним вызовом
Формат файла удобнее длинной командной строки и повторяем при инциденте. curl пишет времена в секундах с долями. -o /dev/null убирает тело из терминала; оно всё равно загружается, поэтому time_total учитывает передачу. -L добавляйте только когда хотите измерить всю цепочку редиректов; для изоляции одного ответа начните без него.
cat > /tmp/curl-timing.txt <<'EOF'
dns=%{time_namelookup} tcp=%{time_connect} tls=%{time_appconnect} pre=%{time_pretransfer} first=%{time_starttransfer} total=%{time_total} code=%{http_code} redirects=%{num_redirects} ip=%{remote_ip}\n
EOF
curl -sS -o /dev/null --max-time 20 -w @/tmp/curl-timing.txt https://enterno.io/
При аварии сохраните также curl --version, URL, время и место запуска. Сравнение с другой машины без этих условий легко перепутать с изменением самого сайта. Для проблемы DNS отдельно проверьте имя через dig, а для TLS — сертификат и SNI по инструкции OpenSSL.

Вычитайте этапы, а не складывайте значения
По документации libcurl, значения отсчитываются от начала передачи. Полезные приближения: DNS = namelookup; TCP = connect - namelookup; TLS = appconnect - connect; ожидание первого байта после подготовки = starttransfer - pretransfer; получение тела = total - starttransfer. Разность pretransfer - appconnect может включать другие шаги протокола. Для чистого HTTPS без редиректа эта схема обычно понятна; при прокси, повторном соединении и HTTP/2 она требует аккуратности.
| Поле curl | Что заканчивается | Если выросло |
|---|---|---|
time_namelookup | Разрешение имени | Проверьте резолвер и кеш DNS. |
time_connect | TCP-соединение | Смотрите маршрут, потери, адрес и доступность порта. |
time_appconnect | TLS-рукопожатие | Отделите RTT от ошибок TLS и сертификата. |
time_starttransfer | Первый байт ответа | Сопоставьте с журналом приложения и прокси. |
time_total | Полный ответ | Проверьте размер тела, скорость и потоковую передачу. |
Важная ловушка: time_starttransfer не равен чистому времени приложения. В него уже входят DNS, TCP, TLS и отправка запроса. Для наблюдения за сервером нужна метрика внутри сервиса либо хотя бы сравнение с time_pretransfer. Пинг помогает увидеть сетевую доступность, но не заменяет измерение TLS и HTTP.
Контрольный замер трёх сайтов
13 ноября 2026 года мы выполнили по три отдельных вызова curl 8.12.1 с одного хоста srv2029141.hstgr.cloud. Без редиректов для enterno.io, www.cloudflare.com и yandex.com получен HTTP 200. Таблица показывает медианы трёх накопленных отметок в миллисекундах, округлённые до десятых; это снимок маршрута из одной точки, а не сравнение скорости компаний или стран.
| URL | DNS | TCP | TLS | Первый байт | Всего |
|---|---|---|---|---|---|
| enterno.io | 0,8 | 37,8 | 87,8 | 141,7 | 288,0 |
| www.cloudflare.com | 0,7 | 4,5 | 14,7 | 25,9 | 57,7 |
| yandex.com | 0,7 | 41,2 | 85,9 | 204,2 | 358,3 |
Первый вызов к enterno.io дал time_starttransfer=0.144038 и time_total=0.273420. В этом конкретном ответе после первого байта прошло около 129 мс. Причину без серверных трасс не назначаем: тело, буферизация и сеть все возможны. Отдельный тест yandex.ru с -L прошёл через два редиректа; смешивать его времена с запросами без редиректа нельзя. Для непрерывного контроля используйте разбор DNS-расхождений и мониторинг целевого URL.
Как сузить медленный этап
Если выросло DNS-время, повторите запрос к другому резолверу и сравните A/AAAA; в статье о TTL разобрано, почему ответы могут различаться. Если выросло TCP, проверьте IPv4 и IPv6 раздельно, сетевой путь и ближайший прокси. При TLS смотрите SNI, версию и цепочку сертификатов через SSL-проверку. Если задержка после pretransfer, сопоставьте request_id в логах прокси и приложения. Большое total - starttransfer сначала сравните с размером ответа, сжатием и скоростью клиента.
curl -4 -sS -o /dev/null -w @/tmp/curl-timing.txt https://example.com/
curl -6 -sS -o /dev/null -w @/tmp/curl-timing.txt https://example.com/
curl -sS -o /dev/null -w 'redirects=%{num_redirects} redirect_time=%{time_redirect} total=%{time_total}\n' -L https://example.com/
Не ставьте -k в рабочий замер: отключение проверки сертификата меняет условие теста и скрывает дефект доверия. Не объявляйте один результат причинным диагнозом. Сначала повторите серию и сохраните исходный вывод.
Как сделан материал
Команды выполнялись на одном сервере 13 ноября 2026 года с curl 8.12.1 и OpenSSL 3.5.8. В архиве data.json сохранены argv, HTTP-код, IP, число редиректов, все временные поля и exit code для каждой попытки. Три выбранных URL вернули 200 без редиректов; дополнительный yandex.ru показал, почему -L надо учитывать отдельно. Маршрут, кеш и содержание страниц могут измениться; цифры не являются обещанием будущей задержки.
Частые вопросы
Почему time_connect больше DNS-времени?
Это накопленная отметка после TCP, а не отдельная длительность TCP. Приближённое время соединения — connect - namelookup.
Можно ли считать time_starttransfer временем PHP?
Нет. В него входят предыдущие сетевые этапы и работа промежуточных прокси. Смотрите starttransfer - pretransfer и сопоставляйте с серверными трассами.
Почему TLS-время иногда равно нулю?
Соединение могло быть повторно использовано либо запрос не проходил новый TLS-handshake. Проверьте num_connects, протокол, редиректы и условия серии.
Нужен ли -L?
Да, если измеряете пользовательский путь до конечной страницы. Для анализа одного ответа сначала снимите времена без перехода по редиректам, затем измерьте всю цепочку отдельно.