# Latens

## Vad det är

Latens är den tid det tar innan ett system börjar svara: från att en begäran lämnar klienten tills
den första byten av svaret är tillbaka. Den kallas också fördröjning, och för en nätverksväg som
mäts fram och tillbaka talar man om rundturstid, på engelska round-trip time (RTT). Inom
webbprestanda går samma idé under namnet time to first byte (TTFB). Svarstiden är dess större
syskon och räknas ända till den sista byten av svaret.

Latens förväxlas lätt med genomströmning och bandbredd, men de tre svarar på olika frågor.
Bandbredd är hur många bitar en länk kan bära per sekund. Genomströmning är hur mycket arbete ett
system hinner med per sekund. Latens är hur länge ett enskilt arbete väntar. Ett batchjobb som körs
varje natt kan ha utmärkt genomströmning och usel latens, och en chattserver det omvända.

Varje millisekund av den kommer från något av några få ställen:

- **utbredning**, när signalen färdas sträckan: ljus i optisk fiber hinner ungefär 200 km per
  millisekund, så en väg på 1 000 km kostar minst 10 ms fram och tillbaka innan någon programvara
  har kört;
- **överföring**, att lägga ut byten på ledningen, vilket märks för stora nyttolaster på
  långsamma länkar;
- **köande**, att vänta bakom annat arbete i en routers buffert, en trådpool, en anslutningspool
  eller ett lås, den enda delen som växer med lasten;
- **bearbetning**, själva arbetet: databasfrågan, mallen, krypteringen;
- **rundturer i protokollet**, samtalet innan den första användbara byten. En ny HTTPS-anslutning
  behöver först en TCP-handskakning och en TLS-handskakning, och TLS 1.3 kortade sin fullständiga
  handskakning till en enda rundtur.

IETF:s arbetsgrupp IP Performance Metrics spikade nätverksvarianten i RFC 2681: fördröjningen
tur och retur löper från den första biten i ett paket som skickas till den sista biten i svaret som
tas emot. Två av dess val går att föra över till vilken tjänst som helst. Ett svar som aldrig kommer
räknas som odefinierat, informellt oändligt, i stället för att i tysthet lämnas utanför urvalet.
Och den statistik som beskrivs är percentiler, medianen och minimum. RFC:n konstaterar också att
minimum bara speglar utbredning och överföring, medan allt över minimum tyder på trängsel, en
uppdelning som håller lika bra för ett API som för en väg mellan routrar.

För en enskild webbförfrågan delar curl upp väntan i sina steg:

```sh
curl -s -o /dev/null "$URL" -w '
dns        %{time_namelookup}
connect    %{time_connect}
tls        %{time_appconnect}
first byte %{time_starttransfer}
total      %{time_total}
'
```

Varje värde är sekunder sedan starten, så skillnaderna mellan dem är kostnaderna: att slå upp
namnet, att öppna anslutningen, TLS-handskakningen och sedan serverns egen betänketid fram till den
första byten.

## Varför det spelar roll

Latensen är det som användaren känner; genomströmningen är det som serverräkningen speglar. När en
sida är långsam gäller beslutet var pengarna ska läggas, och orsakerna ovan har var sitt botemedel
som inte kan ersätta något av de andra. Avstånd åtgärdas genom att flytta närmare: en cache, ett
CDN, en region nära användarna. Rundturer åtgärdas genom att ha färre av dem: att återanvända
anslutningar, batcha databasfrågor och hämta parallellt. Bearbetning åtgärdas genom att göra mindre
arbete: ett index, en bättre frågeplan. Köande är det enda som åtgärdas med kapacitet. En
databasfråga som tar två sekunder på en server utan last tar två sekunder på en server som är tio
gånger så stor, och därför är mer hårdvara rätt svar på bara en av orsakerna.

Medelvärden får problemet att se mindre ut än det är, eftersom användarna möter svansen. En sida som
anropar tio backend-tjänster parallellt väntar på den långsammaste. Om varje anrop är långsamt 1 %
av tiden, så träffar 1 − 0,99¹⁰, ca 9,6 % av sidladdningarna, minst ett långsamt anrop. En sällsynt
fördröjning i delarna blir en vanlig fördröjning i helheten.

Därför skrivs seriösa mål i percentiler, t.ex. att 99 % av begärandena besvaras inom 300 ms under
30 dagar, och därför är den 99:e percentilen oftast den siffra som är värd att bevaka. Medianen
säger hur tjänsten känns en bra dag; de höga percentilerna säger hur den känns för de kunder som är
på väg att lämna.

## Så ser det ut i praktiken

I en geografisk kartapplikation drabbade latensen vid rendering av kartlager och vid frågor mot
platsdata både användarna och backendens tillförlitlighet. Databasen under, Microsoft SQL Server,
saknade inbyggd geospatial indexering, så den långsamma delen var bearbetning och inte avstånd. Med
[flytten till PostgreSQL och PostGIS](/sv/portfolio/improved-geographical-map-application-performance-by-10x-through-6/)
sjönk den genomsnittliga svarstiden från 2,5 sekunder till under 250 millisekunder, och prestandan
för spatiala databasfrågor förbättrades 10 gånger. Bakom det låg GiST- och SP-GiST-index på de
spatiala kolumnerna, över 50 miljoner poster som migrerades och en konfiguration som finjusterats
för samtidig åtkomst; CPU-belastningen i backend minskade med 65 %.

Latens sätter också ett tak för genomströmningen där många transaktioner slåss om samma rad.
[Anteckningen om låset på en het lagerrad](/sv/notes/selling-limited-stock-without-overselling/)
anger taket för en vara till ungefär det antal försäljningar som ett lås bär, delat med hur länge
låset hålls. Allt som är långsamt inuti låset sänker taket: ett betalningsanrop som görs medan låset
hålls drar ned det till ungefär två försäljningar per sekund. Till och med en skyddsåtgärd har ett
pris här. En synkron standby i PostgreSQL lägger till latens vid varje commit, och det förlänger
precis den låshålltid som taket delas med.

Och för att hitta vart tiden tar vägen registrerar
[den egenbyggda övervakningen på en plattform](/sv/portfolio/built-first-party-error-monitoring-and-tracing-98/)
API-latens i sin egen databas och spårar begäranden med OpenTelemetry, så att en långsam begäran
kan följas genom frontenden, API:t och databasen i stället för att gissas fram.

## Var det går fel

**Medelvärdet döljer svansen.** Ett medelvärde på 100 ms går ihop med att en begäran av femtio tar
tre sekunder. Registrera latensen som ett histogram och läs av dess percentiler. Tänk sedan på hur
de kombineras: den 99:e percentilen från fem servrar kan inte medelvärdesbildas till hela flottans
99:e percentil. Prometheus gör samma poäng i sin egen dokumentation, där kvantiler som beräknats av
en summary inte kan aggregeras, medan histogrammets hinkar kan summeras först och kvantilen tas
fram efteråt.

**Tidtagningen startar på fel ställe.** En server som mäter från det ögonblick då dess hanterare
börjar missar tiden som en begäran tillbringade i lastbalanseraren, i acceptkön eller i väntan på en
anslutning från poolen. Lastgeneratorer som väntar på varje svar innan de skickar nästa begäran
skickar färre begäranden just när systemet står still, så stoppet syns knappt i resultaten. Mät
från klienten också, och låt servern rapportera sin andel i en standardiserad header:

```http
Server-Timing: db;dur=53, app;dur=47.2
```

**Samtalet är för pratigt.** En sida som kör en databasfråga per rad i en lista betalar en rundtur
per rad. Med databasen i en annan region, 30 ms bort räknat tur och retur, kostar hundra rader tre
sekunder innan någon fråga har gjort riktigt arbete. En enda fråga med en join, eller ett enda
batchat anrop, betalar avståndet en gång.

**Omförsök mångfaldigar lasten.** En klient som ger upp efter en sekund och försöker igen tre
gånger gör en långsam server till fyra gånger så mycket trafik, vilket gör den ännu långsammare. Ge
varje begäran en total tidsgräns, vänta exponentiellt längre med slumpmässig spridning (jitter)
mellan försöken och sätt ett tak för antalet omförsök.

## Läs mer

- [RFC 2681: A Round-trip Delay Metric for IPPM](https://www.rfc-editor.org/rfc/rfc2681)
  — fördröjning tur och retur definierad ned till biten, där förlorade svar och percentiler
  hanteras uttryckligen.
- [RFC 7679: A One-Way Delay Metric for IP Performance Metrics](https://www.rfc-editor.org/rfc/rfc7679)
  — motsvarigheten i en riktning, publicerad som internetstandard.
- [Server Timing](https://www.w3.org/TR/server-timing/) — W3C:s header som låter en server tala om
  för webbläsaren vart tiden tog vägen.
- [Histograms and summaries](https://prometheus.io/docs/practices/histograms/) — varför kvantiler
  från en summary inte kan kombineras, medan histogrammets hinkar kan det.
- [RFC 8446: TLS 1.3](https://www.rfc-editor.org/rfc/rfc8446) — handskakningens utformning,
  inklusive den rundtur som den tar bort.

<https://engineer.company/sv/glossary/latency/>
