Gran parte del lavoro che faccio in questi giorni riguarda sistemi multi-thread e/o distribuiti. La maggior parte dei bug riguarda errori di tipo "succede prima", in cui lo sviluppatore assume (erroneamente) che l'evento A si verificherà sempre prima dell'evento B. Ma ogni 1000000a volta il programma viene eseguito, l'evento B viene eseguito per primo e ciò causa imprevedibile comportamento.
Inoltre, non esistono strumenti validi per rilevare i problemi di temporizzazione o persino il danneggiamento dei dati causato dalle condizioni di gara. Strumenti come Helgrind e drd del toolkit Valgrind funzionano alla grande per programmi banali, ma non sono molto utili per diagnosticare sistemi complessi e di grandi dimensioni. Per prima cosa, segnalano falsi positivi abbastanza frequentemente (in particolare Helgrind). Inoltre, è difficile rilevare determinati errori durante l'esecuzione con Helgrind/drd semplicemente perché i programmi in esecuzione su Helgrind funzionano quasi 1000 volte più lentamente e spesso è necessario eseguire un programma per un periodo di tempo pari a per riprodurre la condizione di gara. Inoltre, dal momento che girare con Helgrind cambia totalmente i tempi del programma, potrebbe essere impossibile riprodurre un certo problema di temporizzazione. Questo è il problema con problemi di temporizzazione sottili; sono quasi Heisenbergiani nel senso che alterare un programma per rilevare i problemi di temporizzazione può oscurare il problema originale.
Il fatto triste è che la razza umana non è ancora adeguatamente preparata per gestire software complesso e concorrente. Quindi, sfortunatamente, non esiste un modo semplice per testare l'unità. In particolare per i sistemi distribuiti, è necessario pianificare attentamente il programma utilizzando Lamport's happens-before diagrams per identificare l'ordine necessario degli eventi nel programma. Ma alla fine, non puoi veramente sfuggire al test delle unità a forza bruta con input variabili casualmente. Aiuta anche a variare la frequenza di commutazione del contesto dei thread durante il test unitario, ad es. esegue un altro processo in background che richiede solo cicli della CPU. Inoltre, se si ha accesso a un cluster, è possibile eseguire più test unitari in parallelo, in grado di rilevare i bug molto più rapidamente e risparmiare un sacco di tempo.
fonte
2009-11-14 11:59:05
Grazie per aver segnalato i diagrammi di Lamport! Esistono questi nuovi linguaggi "concorrenti" che nascondono gran parte della complessità del dominio del tempo utilizzando esclusivamente strutture di dati immutabili (ad esempio, Clojure). Ma non sono ancora soluzioni completamente curative (ancora). –
+1 Semplicemente perché questa frase: "Il fatto triste è che la razza umana non è ancora adeguatamente preparata per affrontare software complessi e concomitanti" mi ha ricordato un certo dottor Cooper. –