Qual é o significado da regra 90/10 de otimização de programa?

67

Segundo a Wikipedia, a regra 90/10 da otimização de programas afirma que "90% do tempo de execução de um programa é gasto na execução de 10% do código" (veja o segundo parágrafo aqui ).

Eu realmente não entendo isso. O que exatamente isso significa? Como 90% do tempo de execução pode ser gasto apenas executando 10% do código? E os outros 90% do código então? Como eles podem ser executados em apenas 10% do tempo?

Rakshith Ravi
fonte
50
Algumas partes do código podem ser executadas com mais frequência do que outras. Afinal, é para isso que servem os loops. Na prática, quase sempre algumas partes são executados maneira mais frequentemente do que outros.
Kilian Foth
147
Aguarde até ouvir a regra 90/10 para a duração do projeto de software: “90% do projeto ocupará os primeiros 90% do tempo alocado; os últimos 10% do projeto ocuparão os outros 90% do tempo alocado ”.
Paul D. Waite
3
Confusão aqui: "o tempo é gasto executando". Considere a++; for(i=0;i<100;i++){b++;} for(i=0;i<100;i++){print(xyz);}. Certamente, o primeiro loop for passa muito mais do que a primeira instrução, mas o segundo loop passa ~ 1000x mais tempo que o primeiro loop for, mas não é executado . Ele gasta aguardando impressão . Portanto, há uma diferença entre o tempo gasto na execução e o tempo pelo qual o código é responsável .
Mike Dunlavey
32
@ Paul_D._Waite Eu pensei que 90% do projeto demorou 90% do tempo, 90% do que resta leva outros 90% do tempo, e assim por diante em uma série não-convergente até a conclusão de que nenhum projeto é já terminado ou totalmente corrigido em menos de tempo infinito.
nigel222
9
Para exemplos práticos, alguns códigos nos quais trabalhei (modelos científicos) usaram uma grande quantidade de código (~ 10K linhas) para ler e configurar o modelo e, em seguida, percorreram algumas centenas de linhas para realizar os cálculos reais. Mas esse ciclo curto foi n ^ 4 (três dimensões espaciais iteraram através de muitos milhares de etapas no tempo), então levou alguns dias para computar. Assim, a relação real foi provavelmente mais como 99% / 1% :-)
jamesqf

Respostas:

184

Existem dois princípios básicos em jogo aqui:

  • Algum código é executado com muito mais frequência do que outro código. Por exemplo, algum código de manipulação de erros pode nunca ser usado. Algum código será executado somente quando você iniciar seu programa. Outro código será executado repetidamente enquanto o programa é executado.
  • Algum código leva muito mais tempo para ser executado do que outro código. Por exemplo, uma única linha que executa uma consulta em um banco de dados ou extrai um arquivo da Internet provavelmente levará mais de milhões de operações matemáticas.

A regra 90/10 não é literalmente verdadeira. Varia de acordo com o programa (e duvido que exista alguma base para os números específicos 90 e 10; alguém provavelmente os tirou do ar). Mas o ponto é que, se você precisar que seu programa seja executado mais rapidamente, provavelmente apenas um pequeno número de linhas é significativo para que isso aconteça. Identificar as partes lentas do seu software geralmente é a maior parte da otimização.

Esse é um insight importante e significa que as decisões que parecem contra-intuitivas para um novo desenvolvedor geralmente podem estar corretas. Por exemplo:

  • Há muito código que não vale a pena tornar "melhor" , mesmo que esteja fazendo as coisas de uma maneira simplista e burra. Você poderia escrever um algoritmo de pesquisa mais eficiente para o aplicativo XYZ? Sim, mas na verdade uma comparação simples de cada valor leva uma quantidade trivial de tempo, mesmo que existam milhares de valores. Portanto, simplesmente não vale a pena. Pode ser difícil para os novos desenvolvedores evitarem otimizações desnecessárias, porque em seu programa de graduação gastava muito tempo escrevendo o algoritmo "correto" (o que significa mais eficiente). Mas, no mundo real, o algoritmo correto é aquele que funciona e roda com rapidez suficiente.
  • Alterações que tornam seu código muito mais longo e mais complexo ainda podem ser uma conquista de desempenho. Por exemplo, no aplicativo FOO, pode valer a pena adicionar centenas de linhas de nova lógica, apenas para evitar uma única chamada ao banco de dados.

fonte
6
É importante notar que, com coisas como funções de classificação, é muito mais rápido (em tempo de desenvolvimento) e mais fácil fazer com que algo simples e idiota faça a coisa certa em todos os casos do que obter um algo elegante totalmente funcional e sem erros. (Tho as únicas razões para escrever um tipo algo fora do acadamea estão se você está construindo uma biblioteca ou trabalhando em uma plataforma sem um ...)
StarWeaver
5
Eu acho que você precisa adicionar o link para shouldioptimize.com :)
Ivan Kolmychek
13
Eu acho que o 9010 vem da bem conhecida 80/20 Pareto Princípio en.wikipedia.org/wiki/Pareto_principle
fernando.reyes
2
@ StarWeaver É por isso que as linguagens que tornam a escrita supereficiente tão fácil quanto ou mais fácil do que um tipo de bolha ruim são importantes por lá, como o C ++. Esses algoritmos e códigos "pré-empacotados" podem ser muito otimizados sem causar complexidade no ponto de uso.
Yakk
6
@IvanKolmychek Esse site é enganoso. Claro, esse tipo de análise de custo é um fator a considerar, mas há outros fatores, como a experiência do usuário. Você pode economizar muito dinheiro ao não otimizar, mas também pode perder muito dinheiro se as pessoas deixarem o site frustrado.
jpmc26
21

Esta não é uma lei da natureza, mas uma regra de ouro resultante de uma vasta experiência. Também é conhecida como regra 80/20 e é apenas uma aproximação aproximada.

Loops, Ramos e outro controle de fluxo.

Cada local que possui um if, você terá um ramo que é ocupado com mais frequência do que o outro ramo. Assim, é gasto mais tempo de execução executando essa parte do programa, e não a outra parte.

Cada local que possui um loop que é executado mais de uma vez, você tem um código que é executado mais do que o código circundante. Assim, mais tempo é gasto lá.

Como exemplo, considere:

def DoSomeWork():
    for i in range(1000000):
        DoWork(i)
    except WorkExeption:
        print("Oh No!")

Aqui, o print("Oh No!")único será executado apenas no máximo uma vez, e muitas vezes nunca, enquanto o DoWork(i)ocorrerá cerca de um milhão de vezes.

Caleth
fonte
7
Chamar isso de regra 80/20 pode causar confusão com o princípio de Pareto , que se aplica mais amplamente do que apenas à programação. Talvez 90 e 10 sejam apenas números convenientes que não tenham essa sobreposição de significado.
Trichoplax
29
É uma instância do diretor de Pareto. Ambos os pares de números são igualmente arbitrária
Caleth
2
Há uma base matemática na divisão 80/20 no princípio de Pareto. Não são apenas algumas figuras imaginárias para representar "muito" e "um pouco".
Moyli 25/10/16
11
@Moyli - Sim, "Existe uma base matemática na divisão 80/20 ...", mas no mundo real, ela nunca será (OK, por coincidência, raramente) será exatamente 80/20.
Kevin Fegan
2
@trichoplax o princípio de pareto se aplica muito bem aqui. 20% das causas (as linhas de código) faz com que 80% dos efeitos (o tempo de execução)
njzk2
16

Rotações.

Estou tentado a parar por aí! :-)

Considere este programa

1. do_something

2. loop 10 times
3.    do_another_thing

4.    loop 5 times
5.        do_more_stuff

A linha 1 é executada uma vez, enquanto a linha 3 é executada 10 vezes. Olhando cada linha por vez

1 1   0.8%
2 10  8.3%
3 10  8.3%
4 50 41.3%
5 50 41.3%

Duas linhas representam 83% do tempo de execução (assumindo que todas as linhas demoram aproximadamente o mesmo tempo para serem executadas. Portanto, 40% do programa leva> 80%.

Com exemplos maiores e mais reais, isso aumenta e apenas uma pequena quantidade de linhas é responsável por grande parte do tempo de execução.

A regra 90/10 (ou como às vezes é 80/20) é uma "regra de ouro" - apenas aproximadamente verdadeira.

Veja também Princípio de Pareto

Nick Keighley
fonte
2
Em vez de dizer que é apenas aproximadamente verdade, eu diria que, em muitos casos, pelo menos 90% do tempo será gasto executando uma pequena fração do código - no máximo 10%. Obviamente, seria possível ter programas em que todas as partes passassem a mesma quantidade de tempo em execução, mas isso é raro.
Supercat
+1 para fazer referência ao Princípio de Pareto. Uma explicação mais detalhada pode ser vista neste fantástico vídeo Vsauce .
Radu Murzea 27/10/16
5

Como você perguntou apenas sobre o tempo de execução, este exemplo pode ser útil:

int main() {
    sleep(90); // approximately 10% of the program.
    // other 90% of the program:
    sleep(1);
    sleep(1);
    sleep(1);
    sleep(1);
    sleep(1);
    sleep(1);
    sleep(1);
    sleep(1);
    sleep(1);
    sleep(1);
    return 0;
}

Para ser um pouco mais sério, significa que, no código da vida real, você quase sempre chama uma função pesada em um loop (em vez de sleep(90);), enquanto o restante, 10% do tempo, realiza alguns cálculos de passagem única.

Outro exemplo é o tratamento de erros em alguns serviços de alta disponibilidade. Qualquer serviço altamente disponível é projetado para funcionar por uma quantidade infinita de tempo em condições normais. Ele opera normalmente 99% do tempo, mas ocasionalmente, em caso de erro, executa alguma manipulação e recuperação de erros, que podem ser ainda mais logicamente complexas do que o próprio serviço.

Sergey
fonte
Bom, eu esperava que alguém publicasse esse exemplo extremo, que mostra claramente a diferença.
djechlin
3

O raciocínio 90/10 significa que uma pequena parte do seu código será repetida ou usada mais do que outras. Isso geralmente é usado para sugerir que você concentre 90% do seu esforço de desenvolvimento / otimização nesses 10% do seu código.

Pense em um processador de texto normal, como o Microsoft Word ou o OpenOffice :

  • O diálogo de preferências não é muito usado;
  • As sub-rotinas que desenham caracteres são usadas o tempo todo.

Esse ditado também é usado nas ciências da administração ... Esta é uma lição para a própria vida ... Significado: concentre a maior parte de seus esforços, a fim de obter mais resultados.

Lucas
fonte
6
Se o Microsoft Word é simples, qual é o exemplo de um exemplo complexo?
Peter Mortensen
@PeterMortensen que não faz sentido.
The Great Duck
@PeterMortensen Emacs, obviamente.
muru 28/10
2

Imagine um programa como este:

print "H"
print "e"
print "l"
print "l"
print "o"
for i=0 to 1,000,000
    print "How long now?"
next
print "B"
print "y"
print "e"

Observe como existem 11 linhas aqui onde 3 dos 11 são o loop for, onde quanto tempo é gasto nesse pequeno pedaço de código? Um pouco enquanto as outras 8 linhas estão apenas imprimindo um único caractere. Portanto, lembre-se de que, embora um código possa ser curto, isso não indica com que frequência ele é executado e quanto tempo levará.

JB King
fonte
0

Além do loop, como mencionado por outras ótimas respostas, também existem princípios DRY a serem considerados. Bem escrito, o código orientado a objetos tem muitas partes reutilizáveis. As partes que são reutilizadas, por definição, são usadas pelo menos duas vezes mais que algo que é executado apenas uma vez. Se você tiver muito código OO, poderá potencialmente reutilizar algumas classes e métodos várias vezes e alguns outros pedaços de código apenas uma vez.

Como mencionado em outras respostas, provavelmente é melhor gastar esforços para tornar o código usado com mais frequência melhor do que melhorar o código usado apenas uma única vez.

Marshall Tigerus
fonte
2
Você pode reutilizar muito código, mas tudo pode ser executado com pouca frequência (embora ainda seja crucial).
Peter Mortensen
@PeterMortensen "crucial, mas muitas vezes não" não é o mesmo que "reutilizado quase a cada segundo e que necessitam de ser tão rápido quanto possível"
O Grande Duck
@TheGreatDuck e eu não acho que foi isso que ele quis dizer. Porque você pode ter um código que é executado com pouca frequência, mas deseja que ele aconteça o mais rápido possível. Por exemplo, vamos dar uma recuperação de erro - dependendo do aplicativo, pode ser bom levar algum tempo (5 minutos, uma hora, talvez mais) para que o sistema volte a funcionar. No entanto, se, por exemplo, um sistema de vôo encontrar um erro, você realmente o quer o mais rápido possível. Porque, se isso não acontecer, "irá cair" e "travar" em um sentido muito literal.
VLAZ
Isso parece implicar que o DRY requer OO, o que obviamente não é verdade. A reutilização é igualmente facilitada por funções livres etc.
underscore_d
@ vlaz isso é verdade, mas a coisa é que em um avião .... TUDO precisa correr rápido.
The Great Duck
0

Isso não é uma regra, é apenas um cara que editou a Wikipedia com alguns números retirados do nada e a chamou de regra. Compare com o Princípio de Pareto, que é mais firmemente estabelecido em outros contextos. Eu gostaria de ver quais pesquisas foram feitas (se houver) sobre a precisão dessa "regra".

Mas basicamente a resposta para sua pergunta é: algum código é executado com muito mais frequência do que outro código. Loops são frequentemente a razão disso. Outras razões são chamadas demoradas, por exemplo, para recursos externos, como serviços da Web ou mídia de armazenamento.

Brad Thomas
fonte
É uma coisa legítima que as pessoas usam como regra geral.
The Great Duck
Se você está sugerindo que isso seja amplamente utilizado como regra geral, eu também estaria interessado em ver evidências disso! Ou isso é apenas mais uma opinião tirada do nada, mas implícita como factual?
Brad Thomas
Se você realmente ler o artigo da wikipedia, verá que a citação referida pelo autor da pergunta tem esta citação: amazon.com/Every-Computer-Performance-Book-Computers/dp/… Eu nunca o vi pessoalmente em uso, mas sua postagem pareceu rude e descartada na minha opinião, então eu respondi. Obviamente 10% é um número que alguém inventou. Eu posso fazer o número que quiser, tornando meu programa ineficiente. No entanto, se é ou não um termo usado na engenharia de software, claramente não é discutível, pois quantas pessoas aqui concordam com sua existência.
The Great Duck
Bem, eu não vou comprar o livro apenas para ver a pesquisa a que ele supostamente se refere ... você pode postar uma citação dele que mostre as evidências? Ou você de fato não viu nada?
Brad Thomas
11
@ BradThomas: Evidências contra a teoria de que a regra 90-10 foi inventada por alguém que estava editando a Wikipedia é que ela foi amplamente citada, com os números 90 e 10, muitos anos antes da existência da Wikipedia; o princípio real não é que exatamente 10% do código represente 90% do tempo de execução, mas que, na maioria dos programas, uma pequena parte do código - 10% ou menos , representa uma porção tão grande do tempo de execução - -90% ou mais, que mesmo uma melhoria de 10% no desempenho dessa pequena parte do código reduziria o tempo de execução geral mais do que uma melhoria de 1000x em todo o resto.
Supercat
0

É uma reinterpretação do "princípio de Pareto", que afirma "para muitos eventos, aproximadamente 80% dos efeitos vêm de 20% das causas.", Também conhecida como regra 80/20. Essa regra é aplicada principalmente à economia, por isso faz sentido que ela seja proposta novamente para a programação.

É apenas um padrão que foi observado por um longo período de tempo.

Aqui está um vídeo muito bom sobre padrões como este, e também explica o Princípio de Pareto.

https://www.youtube.com/watch?v=fCn8zs912OE&ab_channel=Vsauce

imnota4
fonte