
Kahoot slet med ytelsen: «Måtte hacke Redux»
Norske Kahoot støtter opptil 2.000 samtidige deltakere – men ytelsen var for dårlig. Slik fikset de det.
– Ingenting kan drepe Redux, men Redux kan drepe ytelsen til appen din.
Det sa Karl Lundfall, tech lead i den norske quiz-plattformen Kahoot, under en presentasjon på React Norway-konferansen i Oslo nylig.
Kahoot har ifølge dem selv hatt mer enn 11 milliarder deltakere fra mer enn 200 land siden selskapet ble etablert i 2012. Appen har nå rundt 10 millioner brukere om dagen.

I gjennomsnitt er det rundt 10 spillere per spill, men det er mulig med opptil 2.000 deltakere – og Kahoot har planer om å øke denne grensen. For en stund siden begynte imidlertid Kahoot å få rapporter om ytelsesproblemer.
– Produktsjefen fortalte meg at noen av de største spillene ikke fungerte så bra, sa Lundfall.
Tung klient, lett server
Kahoot har valgt en arkitektur der de legger mesteparten av spill-logikken på klienten. Dette forenkler serveren og holder også driftskostnadene lave, samt at frontend-utviklere fortløpende kan oppdatere spill-logikken.
Samtidig introduserer denne tilnærmingen også en potensiell ytelses-flaskehals på klienten, siden all bearbeiding og gjengivelse skjer i nettleseren.
Kahoot består av to React-applikasjoner, én for deltakerne og én for den som oppretter Kahoot-en (verten):

- Når deltakerne kobler seg til et spill og for eksempel svarer på et spørsmål, skjer det en sanntids synkronisering av data mellom deltagerne og verten.
- Innkommende meldinger havner i en meldingskø.
- Meldinger fra meldingskøen prosesseres og går via Redux som håndterer spillets tilstand til enhver tid.
- React.js og WebGL-rendringsbiblioteket Pixi.js tegner opp spillet på skjermen til verten.
– Men verten er bare i stand til å taklet et visst antall forespørsler, og hvis deltakerne aggressivt sender meldinger, vil kanskje verten bli overbelastet.
Redux var synderen
Da Kahoot-teamet begynte å få meldinger om at kanskje spillet ikke skalerte godt nok til veldig mange samtidige spillere, begynte de å grave i problemene.
Kahoot startet med et enkelt testverktøy de kalte "Bots-as-a-Service", som spant opp en masse samtidige spillere (boter). Dette var imidlertid litt upålitelig, så verktøyet ble skrevet om i JavaScript – og så brukte man Chrome Devtools til testing.
Neste skritt var litt mer avansert testing med Vitest, React Profiler og React Testing Library, samt Vite bench og ulike analyseverktøy.

– Det første vi fant ut med disse verktøyene, var noe rart som skjedde med Reselect, fortalte Lundfall.
Reselect er et bibliotek som ofte brukes sammen med Redux som gjør at såkalte selektorer i Redux "memoizes" – altså caches for bedre ytelse.
– Noen ganger har du en selektor som aksepterer to argumenter. Det var en bug i Reselect som gjorde at dette ikke ble memoisert riktig. Vi fikset det med å hacke vår egen versjon av createSelector, forklarte Lundfall.
Bugen i Redux ble meldt inn som en issue til Reselect-repoet i Redux sitt Github-repo, der også Kahoots "fiks" er lagt ut:

Mye raskere
Fiksen av Reselect-buggen førte ifølge Lundfall til en tredobling av ytelsen.
I tillegg introduserte Kahoot også noen andre forbedringer, som blant annet et system for prioritering av meldinger, samt at flere meldinger kunne slås sammen (batches) til én i stedet for mange oppdateringer:

Sluttresultatet ble at Kahoot klarte å optimalisere ytelsen uten at de måtte skrive noe av funksjonaliteten på nytt, eller endre teknologistacken sin.
– Noen ganger er konvensjonelle verktøy overvurdert, avsluttet Lundfall.