Stoppet en applikasjon som fylte minnet med 41 MB i sekundet — registrert 111 GB komprimerte sider på en maskin med 36 GB — ved å begrense hver hendelsesstrøm, abonnere etter hendelsestype og sette et frekvensbudsjett på loggingen, som tok 610 996 logglinjer ned til 1 411.
Arbeidet utført: september 2026
41 MB minnevekst per sekund, stoppet
Situasjon. Appen fylte minnet til operativsystemet drepte den. Den registrerte hendelsen nådde 111 GB komprimerte sider på en maskin med 36 GB, med en stigning på rundt 41 MB i sekundet, og loggfilen for én kort økt hadde 610 996 linjer. En maskin i den tilstanden er ikke treg, den er ubrukelig — prosessen drepes først etter at swappingen allerede har fått alt annet på skrivebordet til å slutte å svare.
Oppgave. Veksten måtte finnes, ikke gjettes, og hver ubegrenset kodevei måtte få en grense, fordi én begrenset kø ved siden av tre ubegrensede ikke er en løsning.
Handling. Det var tre årsaker som multipliserte hverandre, og det er multiplikasjonen som forklarer farten. Hendelsesstrømmen fra kjernen ble konsumert uten noen grense, så hendelsene kom raskere enn grensesnittet kunne behandle dem, og etterslepet ble beholdt i stedet for forkastet. Hver abonnent mottok hver hendelse og filtrerte etterpå, så kostnaden for én hendelse ble ganget med antall lyttere, og hver lytters filtrering allokerte minne. Og loggingen hadde ikke noe budsjett, så hver hendelse ga logglinjer — og det er leddet som forsterker alt det andre, fordi loggmengden var proporsjonal med mengden av det som gikk galt. Rettingen tok tak i alle tre: begrensede buffere med en eksplisitt regel for hva som skjer når de blir fulle, abonnement per hendelsestype så en lytter bare vekkes for hendelser den vil ha, og et frekvensbudsjett for loggingen som slår sammen gjentakelser i stedet for å skrive hver enkelt. En regresjonstest kjører en høy hendelsesrate og verifiserer at minnetaket holder, så grensen er en egenskap ved bygget og ikke en kommentar.
Resultat. Minnebruken holder seg flat under vedvarende last, og den samme økten som ga 610 996 logglinjer, gir 1 411. Den ærlige merknaden er at frekvensbudsjettet for loggingen kaster informasjon: når noe går raskt galt nå, er sporet av det bevisst ufullstendig, og det er en avveining gjort med åpne øyne mot alternativet, en maskin som stopper opp.
Se tilbake på Bygde en native meldingsklient for macOS i Swift 6 og SwiftUI — 11 141 linjer fordelt på 53 filer — over C‑grensesnittet til en Rust‑kjerne lenket inn som et statisk arkiv fra en låst revisjon. Les videre: Tok i bruk fullstendig streng samtidighet i Swift 6 uten actors, og koblet en blokkerende C‑hendelsesløkke til main actor gjennom én produsent, én konsument og én rekkefølge — etter å ha slått fast at én task per hendelse mister rekkefølgen grensesnittet er avhengig av. Eller ta en titt på hele porteføljen.
Overfor kunder kaller vi denne Stoppet: en app som slukte 41 MB i sekundet — se den sammen med de andre sakene.
Ett stykke av en lengre oversikt — og den ligger i sin helhet her.
Hver oppføring er skrevet på samme måte: situasjonen, oppgaven, hva vi gjorde, og hva som endret seg.