Deve-se testar a complexidade algorítmica? Se sim, como?


14

Digamos que estou implementando algo simples, como pesquisar uma lista / matriz classificada. A função (em c #) seria semelhante a:

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

Eu poderia implementar e testar isso em termos de funcionalidade, mas, por razões óbvias, eu normalmente preferiria uma pesquisa binária a uma pesquisa linear ou algo intencionalmente estúpido.

Portanto, minha pergunta é: devemos tentar escrever testes que garantam desempenho em termos de complexidade algorítmica e, em caso afirmativo, como?

Comecei a argumentar nos dois lados da parte "você deveria" desta pergunta, mas eu gostaria de ver o que as pessoas dizem sem meus argumentos para induzi-las.

Em termos de "como", isso fica muito interessante :) Você pode parametrizar o operador de comparação e fazer um teste cujo operador de comparação conta comparações ou algo parecido. Mas só porque você pode, não significa que você deveria ...

Alguém mais considerou isso (provavelmente)? Obrigado.


@ steenhulthin - Vou deixar isso ferver aqui e conferir. Eu nunca tinha estado lá.
SirPentor

btw, boa pergunta. +1
Rafael Colucci

Respostas:


13

A complexidade algorítmica é uma construção teórica e, como tal, é melhor "testada" com um lápis e papel. Não pode ser utilmente testado mecanicamente.

O desempenho absoluto pode ser testado mecanicamente e pode fazer testes de unidade úteis. Se o desempenho for importante, você poderá especificar um limite: "essa consulta não deve demorar mais de 50 ms para ser executada em 10 6 números e não mais que 60ms em 10 7 números". Para o qual você pode construir um teste de unidade.

O usuário final não se importa se seu algoritmo é linear ou logarítmico; eles se importam se a interface do usuário ainda responde instantaneamente, mesmo quando possuem um ano de dados no aplicativo.


Este é o meu instinto também. Mas o que me fez pensar sobre isso é quando garantias de desempenho em estruturas. Exemplo: se bem me lembro, o stl tem algumas garantias em torno da complexidade algorítmica (pode estar desativado aqui).
SirPentor

Só porque uma biblioteca fornece algumas garantias não significa que elas precisam ser testadas por unidade.
svick

Tobias Brick: Testar algo e definir algo são duas coisas diferentes.
DeadMG

Demonstrar desempenho é difícil. Envolve muitos pontos de amostra para diferentes parâmetros. É mais fácil quando as funções individuais são triviais, mas além disso ... Sua carga, sua RAM, velocidade do barramento frontal, CPU, número de núcleos, agressividade do compilador, grau de poluição do registro afetarão o tempo de execução de um determinado amostra.
Job

3

Embora eu não tenha certeza se essa ferramenta será particularmente útil para testes de unidade, o artigo "Complexidade computacional empírica" de Goldsmith, Aiken e Wilkerson descreve um método para instrumentar código e observar seu comportamento dinâmico em um conjunto de várias entradas para empiricamente derivar sua complexidade assintótica. O programa descrito no documento é de código aberto e está disponível aqui .

Espero que isto ajude!


0

O principal é experimentá-lo com big data e ver se leva muito tempo.

Na minha experiência de ajuste de desempenho, como neste exemplo , o que acontece é que, se algum algoritmo é (por exemplo) O (n ^ 2), pode ser ótimo, desde que a porcentagem de tempo que leva nunca chegue ao radar.

No entanto, quando é fornecido um conjunto de dados de um tamanho que pode não ser visto, mas uma vez por ano, a fração do tempo total sugado por esse algoritmo pode se tornar catastroficamente dominante.

Se você pode fazer isso acontecer nos testes, isso é uma coisa muito boa, porque é extremamente fácil encontrar o problema, como se fosse um loop infinito real.


0

Eu não acho que o que você quer fazer é Teste de Unidade.

AFAIK, o teste de unidade é apenas para garantir que o código faça o que deve fazer e não se concentre no desempenho.

Da Wikipedia : Não se pode esperar que os testes detectem todos os erros do programa: é impossível avaliar todos os caminhos de execução em todos os programas, exceto os mais triviais. O mesmo vale para testes de unidade. Além disso, o teste de unidade por definição apenas testa a funcionalidade das próprias unidades. Portanto, ele não detectará erros de integração ou erros mais amplos no nível do sistema (como funções executadas em várias unidades ou áreas de teste não funcionais, como desempenho). O teste de unidade deve ser realizado em conjunto com outras atividades de teste de software. Como todas as formas de teste de software, os testes de unidade podem mostrar apenas a presença de erros; eles não podem mostrar a ausência de erros.

Existem outros tipos de ferramentas e padrões para medir o desempenho. Um dos quais me lembro agora é o teste de aceitação focado em requisitos não funcionais.

Existem poucos outros como testes de desempenho (que usam testes de estresse, testes de carga, etc.).

Você também pode usar algumas ferramentas de estresse junto com uma ferramenta de construção (ant, studio de criação automatizada) como parte de suas etapas de implantação (é o que eu faço).

Portanto, a resposta curta é não, você não deve se preocupar com isso ao testar um código por unidade.


0

Passar no comparador e manter o controle do número de vezes que é chamado funcionará com propósitos simples, como verificar se o número de comparações ao fazer uma pesquisa em uma entrada fixa (por exemplo new int[] { 1,2,3, ... , 1024 }) permanece abaixo de 10. Isso será pelo menos Esclareça suas intenções sobre como o algoritmo deve se comportar.

Não acho que os testes de unidade sejam o caminho certo para verificar se seu algoritmo é O (log n); isso exigiria muita geração aleatória de dados, algum ajuste de curva e provavelmente estatísticas genéricas para determinar se vários pontos de dados se encaixam no tempo de execução esperado. (Para esse algoritmo, provavelmente é possível, mas se você começar a classificar, etc., será difícil atingir repetidamente os piores cenários).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.