Fragen? Antworten! Siehe auch: Alternativlos
Daher lese ich sehr gerne Post-Mortems. Hier hat Netflix einen schönen publiziert. Der hat mich ziemlich aus der Bahn geworfen.
Ich fasse mal grob zusammen. Die hatten da Abspiel-Ruckeln auf einem Gerät, und beim Debuggen haben sie rausgefunden, dass ihre Softwarearchitektur schlecht war. Die hat bei einem Scheduler-Framework von Android einen Callback in 15 Millisekunden beantragt, und hat dann Audiodaten für einen Frame rausgeschrieben.
Im Allgemeinen kam der Callback auch nach 15 ms, aber halt nicht immer. Manchmal kam der auch erst nach 55 ms.
Das war ein Bug in Android. Das will ich auch gar nicht schönreden.
Aber was mich daran irritiert: Wenn du beim System oder sonstwo einen Callback beantragst, dann musst du immer davon ausgehen, dass der zu spät kommt oder einer ausfällt. Wir haben es hier mit Best Effort zu tun, im ganzen System. Es könnte z.B. sein, dass das Gerät heißläuft und daher den CPU-Takt runterschraubt und dann für deine beantragten Events nicht genug Luft war. Oder es könnte sein, dass der Speicher knapp wurde, weil eine andere App irgendwas krasses gemacht hat, und das System dann Speicher von deiner App rausgeschmissen hat, um den Bedarf zu befriedigen. Der kann dann wieder reingeladen werden, aber das dauert halt Zeit.
Kurz gesagt: Wenn du dem System sagst, du willst jetzt 15 ms Pause machen, dann hast du genau eine tatsächliche Zusage: Es sind mindestens 15 ms. Nicht höchstens. Mindestens!
Mit anderen Worten: Dein Handler muss immer davon ausgehen, dass da ein Event verlorengegangen ist und in dem Fall dann halt mehr Audiodaten rausschreiben, um nicht ins Stocken zu geraten.
Und das führt dann dazu, dass man auch den Fall abhandeln muss, wo man ein Event zweimal kriegt, denn möglicherweise kommt das erste Event zu spät, schreibt dann zwei Frames raus, und dann kommt direkt das Event für den nächsten Frame, den man jetzt aber schon rausgeschrieben hatte.
Ich bin einigermaßen irritiert, dass Netflix ihre Software nicht so designed hat, dass sie mit dieser Art von Unvorhersehbarkeit klarkommt und das on the fly kompensiert. Ich hätte gedacht, dass das absolute Mindestanforderung an solche Systeme ist. Mir wäre das gar nicht in den Sinn gekommen, ein System zu bauen, was das nicht tut.
Die Lektion ist, dass man bei der API-Dokumentation auch offensichtliche Dinge immer explizit hinschreiben muss. Nur weil du das für offensichtlich hältst, heißt das nicht, dass es auch alle anderen für offensichtlich halten. Als Beispiel will ich hier mal die Man Page von nanosleep(2) zitieren:
If the interval specified in req is not an exact multiple of the granularity underlying clock (see time(7)), then the interval will be rounded up to the next multiple. Furthermore, after the sleep completes, there may still be a delay before the CPU becomes free to once again execute the calling thread.
Ich kenne jetzt diese Android-API nicht, weil ich noch nie Android programmiert habe, aber ich vermute mal, wenn das da so klar dokumentiert gewesen wäre, hätten die Netflix-Leute ihren Dienst nicht auf der Annahme fußen lassen, dass das immer alles perfekt genau wie beantragt reinkommt.