Todo mundo diz que devo fazer meu código modular, mas não é menos eficiente se eu usar mais chamadas de método em vez de menos, mas maiores, métodos? Qual é a diferença em Java, C ou C ++ para esse assunto?
Entendo que é mais fácil editar, ler e entender, especialmente em um grupo. Portanto, a perda de tempo de computação é insignificante em comparação com os benefícios de limpeza do código?
java
c++
c
efficiency
fatsokol
fonte
fonte
Respostas:
Sim, é irrelevante.
Os computadores são mecanismos de execução incansáveis e quase perfeitos, trabalhando a velocidades totalmente incomparáveis aos do cérebro. Embora exista uma quantidade mensurável de tempo que uma chamada de função adiciona ao tempo de execução de um programa, isso não é nada comparado ao tempo adicional necessário para o cérebro da próxima pessoa envolvida com o código quando eles precisam desemaranhar a rotina ilegível até começar a entender como trabalhar com isso. Você pode tentar o cálculo de uma piada - suponha que seu código tenha que ser mantido apenas uma vez e que adicione apenas meia hora ao tempo necessário para que alguém chegue a um acordo com o código. Pegue a velocidade do clock do processador e calcule: quantas vezes o código precisaria executar para sonhar em compensar isso?
Em resumo, sentir pena da CPU é completamente, totalmente equivocado 99,99% do tempo. Para os casos raros restantes, use criadores de perfil. Você não assuma que você pode detectar esses casos - você não pode.
fonte
Depende.
No mundo glacialmente lento que é a programação da Web, onde tudo acontece em velocidades humanas, a programação pesada de métodos, em que o custo da chamada de método é comparável ou excede o custo do processamento feito pelo método, provavelmente não importa .
No mundo da programação de sistemas embarcados e manipuladores de interrupções para interrupções de alta taxa, isso certamente importa. Nesse ambiente, os modelos usuais de "acesso à memória são baratos" e "o processador é infinitamente rápido" se decompõem. Vi o que acontece quando um programador orientado a objetos de mainframe escreve seu primeiro manipulador de interrupções de alta taxa. Não foi bonito.
Vários anos atrás, eu estava colorindo blob de conectividade de 8 vias não-recursivas em imagens FLIR em tempo real, no que era naquele momento um processador decente. A primeira tentativa usou uma chamada de sub-rotina e a sobrecarga da chamada de sub-rotina comeu o processador vivo. (4 chamadas POR PIXEL x 64K pixels por quadro x 30 quadros por segundo = você descobre). A segunda tentativa transformou a sub-rotina em uma macro C, sem perda de legibilidade, e tudo foi rosas.
Você precisa olhar muito para o que está fazendo e para o ambiente em que estará fazendo isso.
fonte
Primeiro de tudo: os programas em um idioma superior são para serem lidos por seres humanos e não por máquinas.
Então escreva os programas para que você os entenda. Não pense em desempenho (se você realmente tiver problemas de desempenho, crie um perfil de seu aplicativo e aprimore o desempenho onde for necessário).
Mesmo que seja verdade que chamar um método ou função exija alguma sobrecarga, isso não importa. Hoje, os compiladores devem poder compilar seu código em uma linguagem de máquina eficiente, para que o código gerado seja eficiente para a arquitetura de destino. Use as opções de otimização do seu compilador para obter o código eficiente.
fonte
Normalmente, quando você teria uma função grande e a dividiria em várias menores, essas menores serão incorporadas porque a única desvantagem de inlining (repetindo muito as mesmas instruções) não é relevante nesse caso. Isso significa que seu código funcionará como se você tivesse escrito uma função grande.
Se eles não estiverem embutidos por algum motivo e isso se tornar um problema de desempenho, considere a inclusão manual. Nem todos os aplicativos são formulários CRUD em rede com enormes latências intrínsecas.
fonte
Provavelmente não há custo de computação. Geralmente, os compiladores / JITs nos últimos 10 a 20 anos lidam com a função embutida perfeitamente. Para o C / C ++, geralmente é limitado a funções 'inlináveis' (ou seja, a definição de função está disponível para o compilador durante a compilação - ou seja, está no cabeçalho do mesmo arquivo), mas as técnicas atuais de LTO superam isso.
Se você dedica algum tempo à otimização, depende da área em que está trabalhando. Se você lida com aplicativos 'normais' que passam a maior parte do tempo aguardando entrada - provavelmente não deve se preocupar com otimizações, a menos que o aplicativo 'pareça' lento.
Mesmo nesses casos, você deve se concentrar em muitas coisas antes de fazer a micro-otimização:
O(n)
paraO(log n)
pode ter um impacto muito maior do que qualquer coisa que você possa obter com a micro-otimização.List
quando precisar,HashSet
para terO(n)
pesquisas quando puderO(1)
.Mesmo que você decida executar micro-otimização (o que praticamente significa que seu software é usado em HPC, incorporado ou usado apenas por um número muito grande de pessoas - caso contrário, o custo adicional de manutenção supera os custos de tempo do computador). para identificar os pontos ativos (kernels) que você deseja acelerar. Mas então você provavelmente deveria:
Como observação final. Normalmente, o único problema que você tem com as chamadas de método é os saltos indiretos (métodos virtuais) que não foram previstos pelo preditor de ramificação (infelizmente o salto indireto é o caso mais difícil). Contudo:
fonte
Minha resposta provavelmente não se expandirá muito nas respostas existentes, mas acho que meus dois centavos podem ser úteis.
Primeiramente; Sim, por modularidade, você geralmente abre mão de algum nível de tempo de execução. Escrever tudo no código de montagem fornecerá a melhor velocidade. Dito isto...
Você conhece o YouTube? Provavelmente o site com maior largura de banda existente ou o segundo na Netflix? Eles escrevem uma grande parte de seu código em Python, que é uma linguagem altamente modular, não totalmente construída para um desempenho de alto nível.
O problema é que, quando algo está errado, e os usuários estão reclamando sobre o carregamento lento dos vídeos, não há muitos cenários em que essa lentidão seria atribuída à lenta velocidade de execução do Python. No entanto, a rápida recompilação do Python e sua capacidade modular de tentar coisas novas sem verificação de tipo provavelmente permitirão que os engenheiros depurem o que está errado muito rapidamente ("Uau. Nosso novo estagiário escreveu um loop que faz uma nova subconsulta SQL para TODOS os resultados. ") ou (" Ah, o Firefox descontinuou o antigo formato de cabeçalho de cache; e eles criaram uma biblioteca Python para configurar facilmente o novo ")
Nesse sentido, mesmo em termos de tempo de execução, uma linguagem modular pode ser considerada mais rápida, porque depois que você descobrir quais são seus gargalos, provavelmente ficará mais fácil reorganizar seu código para que ele funcione da melhor maneira. Muitos engenheiros lhe dirão que os resultados de desempenho pesado não estavam onde eles pensavam que estavam (e, na verdade, as coisas que eles otimizaram eram pouco necessárias; ou nem funcionavam da maneira que esperavam!)
fonte
Sim e não. Como outros já observamos o programa para facilitar a leitura primeiro, depois a eficiência. No entanto, existem práticas padrão que são legíveis e eficientes. A maioria dos códigos é executada com pouca frequência e você não terá muita vantagem em otimizá-lo.
O Java pode incorporar chamadas de função menores, portanto, há poucas razões para evitar a gravação das funções. Os otimizadores tendem a funcionar melhor com códigos mais simples e fáceis de ler. Existem estudos que mostram atalhos que teoricamente deveriam ser executados mais rapidamente, na verdade, levam mais tempo. É provável que o compilador JIT funcione melhor, o código é menor e as peças executadas com frequência podem ser identificadas e otimizadas. Eu não tentei, mas esperaria que uma função grande, chamada relativamente raramente, não fosse compilada.
Provavelmente isso não se aplica ao Java, mas um estudo descobriu que funções maiores na verdade foram mais lentas devido à exigência de um modelo de referência de memória diferente. Isso foi específico do hardware e do otimizador. Para módulos menores, foram utilizadas instruções que funcionavam em uma página de memória. Elas eram mais rápidas e menores do que as instruções necessárias quando a função não se encaixava na página.
Há casos em que vale a pena otimizar o código, mas geralmente é necessário criar um perfil do código para determinar onde está. Acho que muitas vezes não é o código que eu esperava.
fonte