Si dovrebbe testare la complessità algoritmica? Se é cosi, come?


14

Diciamo che sto implementando qualcosa di semplice come cercare un elenco / array ordinato. La funzione (in c #) sarebbe simile a:

static int FindIndex(int[] sortedList, int i);

Potrei implementarlo e testarlo in termini di funzionalità, ma per ovvie ragioni di solito preferirei una ricerca binaria rispetto a una ricerca lineare o qualcosa di intenzionalmente stupido.

Quindi la mia domanda è: dovremmo tentare di scrivere test che garantiscano prestazioni in termini di complessità algoritmica e, in caso affermativo, come?

Ho iniziato a fare argomenti su entrambi i lati della parte "dovresti" di questa domanda, ma mi piacerebbe vedere cosa dicono le persone senza i miei argomenti per spingerli.

In termini di "come", diventa molto interessante :) Potresti vedere parametrizzare l'operatore di confronto e avere un test il cui operatore di confronto conta i confronti o qualcosa del genere. Ma solo perché puoi non significa che dovresti ...

Qualcun altro ha considerato questo (probabilmente)? Grazie.


@ steenhulthin - Lascerò questo sobbollire qui e dare un'occhiata. Non ci ero mai stato.
SirPentor,

a proposito, bella domanda. +1
Rafael Colucci,

Risposte:


13

La complessità algoritmica è un costrutto teorico e come tale è meglio "testata" con una matita e un foglio di carta. Non può essere utilmente testato meccanicamente.

Le prestazioni assolute possono essere testate meccanicamente e possono essere utili test unitari. Se le prestazioni sono importanti, è possibile specificare una soglia: "questa query non dovrebbe richiedere più di 50ms per essere eseguita su 10 6 numeri e non più di 60ms su 10 7 numeri". Per cui puoi costruire un test unitario.

All'utente finale non importa se il tuo algoritmo è lineare o logaritmico; a loro importa se la loro UI continua a rispondere istantaneamente anche quando hanno un anno di dati nell'app.


Anche questo è il mio istinto. Ma quello che mi ha fatto pensare è quando le prestazioni sono garantite sui framework. Esempio: se ricordo bene, lo stl ha alcune garanzie sulla complessità algoritmica (potrebbe essere spento qui).
SirPentor,

Solo perché una libreria fornisce alcune garanzie non significa che devono essere testabili in unità.
svick

@Tobias Brick: testare qualcosa e definire qualcosa sono due cose diverse.
DeadMG,

Dimostrare prestazioni è difficile. Implica molti punti campione per vari parametri. È più facile quando le singole funzioni sono banali, ma oltre a ciò ... Il tuo carico, la tua RAM, la velocità del bus anteriore, la CPU, il numero di core, l'aggressività del compilatore, il grado di inquinamento del registro influenzeranno tutti il ​​tempo di esecuzione di un particolare campione.
Giobbe

3

Anche se non sono sicuro che questo strumento sarà particolarmente utile per i test unitari, l'articolo "Empirical Computational Complexity" di Goldsmith, Aiken e Wilkerson descrive un metodo per strumentare il codice e osservare il suo comportamento dinamico su un insieme di vari input per empiricamente deriva la sua complessità asintotica. Il programma descritto nel documento è open source ed è disponibile qui .

Spero che sia di aiuto!


0

La cosa principale è provarlo con i big data e vedere se ci vuole troppo tempo.

Nella mia esperienza di ottimizzazione delle prestazioni, come in questo esempio , ciò che accade è se un algoritmo è (ad esempio) O (n ^ 2) potrebbe andare bene fintanto che la percentuale di tempo impiegata non arriva mai sul radar.

Tuttavia, quando viene fornito un set di dati di dimensioni che potrebbero non essere visibili ma una volta all'anno, la frazione di tempo totale assorbita da tale algoritmo può diventare catastroficamente dominante.

Se riesci a farlo accadere durante i test, questa è un'ottima cosa, perché è estremamente facile trovare il problema, proprio come se fosse un vero e proprio ciclo infinito.


0

Non penso che quello che vuoi fare sia il test unitario.

AFAIK, il test unitario è solo per assicurarsi che il codice faccia quello che dovrebbe fare e non si concentri sulle prestazioni.

Da Wikipedia : Non ci si può aspettare che i test rilevino tutti gli errori nel programma: è impossibile valutare ogni percorso di esecuzione in tutti i programmi tranne quelli più banali. Lo stesso vale per i test unitari. Inoltre, i test unitari per definizione verificano solo la funzionalità delle unità stesse. Pertanto, non rileverà errori di integrazione o errori a livello di sistema più ampi (come funzioni eseguite su più unità o aree di test non funzionali come le prestazioni). I test unitari devono essere eseguiti insieme ad altre attività di test del software. Come tutte le forme di test del software, i test unitari possono solo mostrare la presenza di errori; non possono mostrare l'assenza di errori.

Esistono altri tipi di strumenti e modelli per misurare le prestazioni. Una delle cose che ricordo ora è il test di accettazione incentrato su requisiti non funzionali.

Ce ne sono altri come il test delle prestazioni (che utilizza stress test, test di carico, ecc.).

È inoltre possibile utilizzare alcuni strumenti di stress insieme a uno strumento di compilazione (formica, studio di compilazione automatizzato) come parte dei passaggi di distribuzione (è quello che faccio).

Quindi la risposta breve è no, non dovresti preoccuparti di ciò quando l'unità verifica un codice.


0

Passare nel comparatore e fare in modo che tenga traccia del numero di volte che viene chiamato funzionerà per scopi semplici come verificare che il numero di confronti quando si esegue una ricerca in un input fisso (diciamo new int[] { 1,2,3, ... , 1024 }) rimanga inferiore a 10. Questo almeno chiarisci le tue intenzioni su come dovrebbe comportarsi l'algoritmo.

Non credo che i test unitari siano la strada giusta da percorrere per verificare che l'algoritmo sia O (log n); ciò richiederebbe molta generazione casuale di dati, un certo adattamento della curva e probabilmente statistiche nodose per determinare se un gruppo di punti dati si adatta al tempo di esecuzione previsto. (Per questo algoritmo è probabilmente fattibile, ma se inizi a selezionare l'ordinamento ecc. Diventerà difficile colpire ripetutamente gli scenari peggiori).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.