2009-04-15 15 views
8

Sto lavorando a un progetto che necessita seriamente di alcune regolazioni delle prestazioni.Le migliori pratiche di test delle prestazioni quando si esegue TDD?

Come si scrive un test che non riesce se le mie ottimizzazioni non migliorano la velocità del programma?

Elaborare un po ':

Il problema non è scoprire quali parti per ottimizzare. Posso usare vari strumenti di profilazione e benchmark per questo.

Il problema sta utilizzando i test automatizzati per documentare che un'ottimizzazione specifica ha effettivamente avuto l'effetto desiderato. Sarebbe anche altamente auspicabile se potessi usare la suite di test per scoprire in futuro possibili regressioni delle prestazioni.

Suppongo che potrei semplicemente eseguire i miei strumenti di profilazione per ottenere alcuni valori e quindi affermare che il mio codice ottimizzato produce valori migliori. Il problema ovvio con ciò, tuttavia, è che i valori di benchmark non sono valori difficili. Variano con l'ambiente locale.

Quindi, è la risposta a utilizzare sempre la stessa macchina per eseguire questo tipo di test di integrazione? In tal caso, dovresti comunque avere una certa sfocatura nei risultati, poiché anche gli stessi risultati di benchmarking dell'hardware possono variare. Come quindi tenerne conto?

O forse la risposta è mantenere versioni precedenti del programma e confrontare i risultati prima e dopo? Questo sarebbe il mio metodo preferito, dal momento che è essenzialmente agnostico dell'ambiente. Qualcuno ha esperienza con questo approccio? Immagino che sarebbe necessario mantenere una versione precedente solo se è possibile eseguire tutti i test se le prestazioni dell'ultima versione sono almeno altrettanto buone della versione precedente.

risposta

3

Per prima cosa è necessario stabilire alcuni criteri per prestazioni accettabili, quindi è necessario escogitare un test che non rispetterà tale criterio quando si utilizza il codice esistente, quindi è necessario modificare il codice per le prestazioni fino a quando non supera il test. Probabilmente avrai più di un criterio per le prestazioni e dovresti sicuramente avere più di un test.

+0

Configura questa asserzione per il controllo di revisione? Ti aspetti che venga estratto su più di un tipo di macchina? Se è così (come immagino), come si fornisce ragionevole aspettativa che le proprie asserzioni siano appropriate su una macchina più lenta/più veloce? – bukzor

2

Registrare il tempo di esecuzione del codice corrente.

if (newCode.RunningTime >= oldCode.RunningTime) Fail 
+1

Anche nel sistema più ben educato, questo produrrà un falso positivo (fallimento quando tutto va bene) il 50% delle volte; questa è una soluzione inutilizzabile. – bukzor

3

In molte applicazioni server (potrebbe non essere il vostro caso) problema di prestazioni manifestano solo sotto l'accesso simultaneo e sotto carico. Misurare il tempo assoluto eseguito da una routine e cercare di migliorarlo non è quindi molto utile. Ci sono problemi con questo metodo anche nelle applicazioni a thread singolo. La misurazione del tempo di routine assoluto si basa sull'orologio fornito dalla piattaforma e questi sono not always very precise; è meglio fare affidamento sul tempo medio che una routine richiede.

Il mio consiglio è:

  • Usa profiling per identificare le routine che eseguono il maggior numero di volte e prendono la maggior parte del tempo.
  • Utilizzare lo strumento come JMeter o Grinder per elaborare casi di test rappresentativi, simulare l'accesso simultaneo, mettere la vostra applicazione sotto stress e misurare (più importante) throughput e tempo medio di risposta. Questo ti darà una migliore idea di come si comporta la tua applicazione come visto dalla prospettiva esterna.

Mentre è possibile utilizzare i test di unità per stabilire alcuni aspetti non funzionali della propria applicazione, ritengo che l'approccio sopra riportato fornirà risultati migliori durante il processo di ottimizzazione. Quando si inseriscono asserzioni relative al tempo nei test delle unità, sarà necessario scegliere alcuni valori approssimativi: il tempo può variare a seconda dell'ambiente in cui si sta utilizzando per eseguire i test unitari. Non vuoi che i test falliscano solo perché alcuni dei tuoi colleghi stanno utilizzando hardware inferiore.

L'ottimizzazione consiste nel trovare le cose giuste da sintonizzare. Hai già un codice funzionante, quindi posizionare le asserzioni relative alle prestazioni a posteriori e senza stabilire sezioni critiche di codice potrebbe portare a perdere un sacco di tempo per ottimizzare i componenti non essenziali della tua applicazione.

+0

"il tempo può variare in base all'ambiente in uso per eseguire i test dell'unità. Non si desidera che i test falliscano solo perché alcuni dei vostri colleghi utilizzano hardware inferiore." Questo è esattamente giusto, e in parte ciò che causa il mio mal di testa. – KaptajnKold

+0

Dopo aver regolato il sistema, come si impedisce la regressione? In tutti gli altri scenari di regressione del software, la soluzione è aggiungere un'asserzione alla suite di test. – bukzor

1

Eseguire i test + profiling nel server CI. È inoltre possibile eseguire periodicamente test di carico.

Sei preoccupato delle differenze (come hai detto), quindi non si tratta di definire un valore assoluto. Avere un passaggio in più che confronta le misure di rendimento di questa corsa con quella dell'ultima build e riportare le differenze come%. Puoi alzare una bandiera rossa per importanti variazioni di tempo.

Se si è preoccupati delle prestazioni, è necessario avere obiettivi chiari che si desidera incontrare e far valere. Dovresti misurare quelli con i test sull'intero sistema. Anche se la logica dell'applicazione è veloce, potresti avere problemi con la vista che ti fa perdere l'obiettivo. Puoi anche combinarlo con l'approccio delle differenze, ma per questi avrai meno tolleranza alle variazioni temporali.

Si noti che è possibile eseguire lo stesso processo nel proprio computer di sviluppo, utilizzando solo le sessioni precedenti in quel computer e non quelle condivise tra gli sviluppatori.

5

Sospetto che l'applicazione di TDD per guidare le prestazioni sia un errore. Con tutti i mezzi, usalo per ottenere un buon design e codice funzionante, e usa i test scritti nel corso di TDD per assicurarti che continui la correttezza - ma una volta che hai un codice ben fattorizzato e una solida serie di test, sei in buona forma sintonizzare, e si applicano tecniche e strumenti diversi (da TDD).

TDD offre una buona progettazione, un codice affidabile e una rete di sicurezza per la copertura di prova. Questo ti mette in un buon posto per la messa a punto, ma penso che, a causa dei problemi che tu e altri avete citato, semplicemente non vi porterà molto più in là lungo la strada della messa a punto. Lo dico come un grande fan e sostenitore del TDD e di un praticante.

+1

+1 concordato. TDD assicura che quando si sintonizza il sistema, non si interrompe la funzionalità –

+0

Questa risposta sarebbe molto più utile se menzionasse * qualsiasi * delle tecniche più adatte. – bukzor

+0

@bukzor L'OP sembra avere un buon controllo sui concetti e gli strumenti di profilazione; la domanda era come applicare TDD a questo. La mia risposta è che probabilmente non è saggio; ci sono molte altre domande e risposte su come ottimizzare le prestazioni del tuo codice. –

0

Per la messa a punto, è possibile confrontare direttamente il vecchio codice e il nuovo codice. Ma non tenere entrambe le copie in giro. Sembra un incubo da gestire. Inoltre, confronti solo una versione con un'altra versione. È possibile che una modifica delle funzionalità rallenti la tua funzione e che sia accettabile per gli utenti.

Personalmente, non ho mai visto i criteri di prestazione del tipo "devono essere più veloci dell'ultima versione", perché è così difficile da misurare.

Si dice "in serio bisogno di ottimizzazione delle prestazioni". Dove? Quali domande? Quali funzioni? Chi dice, il business, gli utenti? Qual è la prestazione accettabile? 3 secondi? 2 secondi? 50 millisecondi?

Il punto di partenza per qualsiasi analisi delle prestazioni è definire i criteri pass/fail. Una volta che hai questo, puoi automatizzare i test delle prestazioni.

Per affidabilità, è possibile utilizzare un (semplice) approccio statistico. Ad esempio, esegui la stessa query nelle stesse condizioni 100 volte.Se il 95% di loro ritorna in meno di secondi, questo è un passaggio.

Personalmente, lo farei al momento dell'integrazione, da una macchina standard o dal server di integrazione stesso. Registra i valori per ogni test da qualche parte (il cruise control ha alcune caratteristiche interessanti per questo genere di cose). Se lo fai, puoi vedere come le prestazioni progrediscono nel tempo e con ogni build. Puoi persino fare un grafico. I manager amano i grafici.

Avere un ambiente stabile è sempre difficile da fare quando si eseguono test delle prestazioni, indipendentemente dal fatto che si stiano eseguendo o meno test automatici. Avrai quel particolare problema indipendentemente da come ti sviluppi (TDD, Cascata, ecc.).

+1

"Non ho mai visto i criteri di prestazione del tipo" devono essere più veloci dell'ultima versione "" Gli utenti di WebKit hanno un criterio di tolleranza zero per le regressioni delle prestazioni. – KaptajnKold

+0

@KatajnKold Questo è fantastico. Ciò significa che l'ho visto una volta :-) –

0

Non abbiamo ancora affrontato questa situazione;) tuttavia, se l'avessi fatto, ecco come farei. (Penso di averlo estratto dal libro di Dave Astel)

Passaggio n. 1: Fornire una specifica per "prestazioni accettabili", per esempio, questo potrebbe significare "L'utente deve essere in grado di fare Y in N secondi (o millisecondi) '
Passo 2: ora scrivi un test non riuscito. Usa la tua classe di timer amichevole (ad esempio .NET ha la classe StopWatch) e Assert.Less(actualTime, MySpec)
Passaggio 3: se il test passa già, hai finito . Se rosso, è necessario ottimizzare e renderlo verde. Non appena il test diventa verde, le prestazioni sono ora "accettabili".

0

kent beck e il suo team hanno automatizzato tutti i test in TDD.

qui per il test delle prestazioni anche noi possiamo automatizzare i test in TDD.

i criteri qui in test di prestazioni è che dovremmo testare le sì o no casi

se conosciamo le specfications ben n buon li possiamo automatizzare anche in TDD

0

Mentre io in linea di massima d'accordo con la risposta di Carl Manaster con gli strumenti moderni è possibile ottenere un po 'di dei vantaggi offerti da TDD per i test funzionali nei test delle prestazioni.

Con la maggior parte dei moderni framework di test delle prestazioni (la maggior parte della mia esperienza è con Gatling, ma credo che lo stesso è vero per le versioni più recenti di maggior parte dei quadri di test delle prestazioni), è possibile integrare test delle prestazioni automatizzati nel costruire l'integrazione continua, e configurare in modo che la generazione di elementi della configurazione fallisca se i requisiti di prestazione non sono soddisfatti.

Quindi, se è possibile concordare preventivamente quali sono i requisiti di prestazione (che per alcune applicazioni possono essere gestiti da SLA concordati con utenti o clienti), questo può fornire un feedback rapido se una modifica ha creato un problema di prestazioni e identificare aree che richiedono miglioramenti delle prestazioni.

I buoni requisiti di prestazione sono in linea con "quando ci sono 5000 ordini all'ora, il 95% dei viaggi degli utenti dovrebbe includere non più di 10 secondi di attesa e nessuna transizione dello schermo impiega più di 1 secondo".

Questo si basa anche sulla distribuzione in un ambiente di prova simile alla produzione nella pipeline CI.

Tuttavia, probabilmente non è ancora una buona idea utilizzare i requisiti di prestazione per guidare il tuo sviluppo nello stesso modo in cui potresti con i requisiti funzionali. Con i requisiti funzionali, in genere è possibile capire se la tua applicazione supererà il test prima di eseguirlo, ed è ragionevole provare a scrivere codice che pensi che passi. Con prestazioni, trying to optimize code whose performance hasn't been measured is a dubious practice.È possibile utilizzare le prestazioni risultati per guidare lo sviluppo delle applicazioni in una certa misura, ma solo i requisiti di prestazione .

Problemi correlati