Eu apenas usei ~ 1 bilhão como contagem para z-index
CSS, e estava pensando nas comparações que deveriam continuar. Existe uma diferença no desempenho no nível da ALU nas comparações entre números muito grandes e números muito pequenos?
Por exemplo, um desses dois trechos seria mais caro que o outro?
snippet 1
for (int i = 0; i < 10000000; i++){
if (i < 10000000000000) {
//do nothing
}
}
snippet 2
for (int i = 0; i < 10000000; i++){
if (i < 1000) {
//do nothing
}
}
performance
cpu
Viziionary
fonte
fonte
CMP
instrução individual da máquina será mais lenta sei
for maior.Respostas:
Todo processador em que trabalhei faz comparação, subtraindo um dos operandos do outro, descartando o resultado e deixando os sinalizadores do processador (zero, negativo etc.) sozinhos. Como a subtração é feita como uma única operação, o conteúdo dos operandos não importa.
A melhor maneira de responder à pergunta com certeza é compilar seu código no assembly e consultar a documentação do processador de destino para obter as instruções geradas. Para CPUs Intel atuais, esse seria o Manual do desenvolvedor de software das arquiteturas Intel 64 e IA-32 .
A descrição da
CMP
instrução ("compare") está no volume 2A, página 3-126 ou página 618 do PDF e descreve sua operação como:Isso significa que o segundo operando é estendido por sinal, se necessário, subtraído do primeiro operando e o resultado colocado em uma área temporária no processador. Em seguida, os sinalizadores de status são definidos da mesma maneira que seriam para a
SUB
instrução ("subtrair") (página 1492 do PDF).Não há menção na documentação
CMP
ouSUB
que os valores dos operandos tenham alguma influência na latência; portanto, qualquer valor usado é seguro.fonte
É muito improvável, a menos que passar de um número pequeno para um número grande altere seu tipo numérico, digamos de um
int
para umlong
. Mesmo assim, a diferença pode não ser significativa. É mais provável que você veja uma diferença se sua linguagem de programação mudar silenciosamente para uma aritmética de precisão arbitrária sob as cobertas.No entanto, seu compilador específico pode estar executando algumas otimizações inteligentes que você não conhece. A maneira que você descobre é medir. Execute um criador de perfil no seu código; veja quais comparações demoram mais. Ou simplesmente inicie e pare um cronômetro.
fonte
Muitos processadores possuem instruções "pequenas" que podem executar operações aritméticas, incluindo comparações, em certos operandos imediatamente especificados. Operandos que não sejam esses valores especiais devem usar um formato de instrução maior ou, em alguns casos, devem usar uma instrução "carregar valor da memória". No conjunto de instruções do ARM Cortex-M3, por exemplo, há pelo menos cinco maneiras pelas quais um valor pode ser comparado a uma constante:
A primeira forma é a menor; a segunda e terceira forma podem ou não ser executadas tão rapidamente, dependendo da velocidade da memória da qual o código é buscado. A quarta forma de formulário quase certamente será mais lenta que as três primeiras e a quinta forma ainda mais lenta, mas a última pode ser usada com qualquer valor de 32 bits.
Nos processadores x86 mais antigos, as instruções de comparação de formato curto seriam executadas mais rapidamente do que as de formato longo, mas muitos processadores mais recentes convertem os formatos longo e curto na mesma representação quando são buscados pela primeira vez e armazenam essa representação uniforme no cache. Assim, enquanto os controladores embarcados (como os encontrados em muitas plataformas móveis) terão uma diferença de velocidade, muitos computadores baseados em x86 não terão.
Observe também que, em muitos casos em que uma constante é muito usada em um loop, um compilador precisará carregar a constante em um registro apenas uma vez - antes do início do loop - tornando as diferenças de tempo irrelevantes. Por outro lado, existem algumas situações, mesmo em pequenos loops, onde isso nem sempre acontece; se um loop é pequeno, mas com execução pesada, ocasionalmente pode haver um desempenho importante entre as comparações que envolvem valores imediatos curtos e as que envolvem valores mais longos.
fonte
A resposta curta para essa pergunta é: não , não há diferença horária para comparar dois números com base na magnitude desses números, supondo que eles sejam armazenados no mesmo tipo de dados (por exemplo, entradas de 32 bits ou comprimentos de 64 bits).
Além disso, até o tamanho da palavra da ALU , é incrivelmente improvável que a comparação de dois números inteiros entre si demore mais de 1 ciclo de clock, pois essa é uma operação trivial equivalente a uma subtração. Eu acho que todas as arquiteturas com as quais eu lidei tiveram comparação de números inteiros de ciclo único.
Os únicos casos em que consigo encontrar que uma comparação de dois números não era uma operação de ciclo único são os seguintes:
fonte
@ A resposta de RobertHarvey é boa; considere esta resposta um complemento à dele.
Você também deve considerar a Predição de ramificação :
Basicamente, no seu exemplo, se a
if
declaração dentro do loop sempre retornar a mesma resposta, o sistema poderá otimizá-la, adivinhando corretamente de que maneira será ramificada. No seu exemplo, como aif
instrução no primeiro caso sempre retorna o mesmo resultado, ela será executada um pouco mais rápido que o segundo caso.Excelente pergunta sobre estouro de pilha sobre o assunto
fonte
Depende da implementação, mas seria muito, muito improvável .
Admito que não li os detalhes de implementação dos vários mecanismos do navegador, e o CSS não especifica nenhum tipo específico de armazenamento para números. Mas acredito que é seguro assumir que todos os principais navegadores estão usando números de ponto flutuante de precisão dupla de 64 bits ("dobra", para emprestar um termo do C / C ++) para lidar com a maioria de suas necessidades numéricas em CSS , porque é isso que JavaScript usa para números e, portanto, usar o mesmo tipo facilita a integração.
Do ponto de vista do computador, todas as duplas carregam a mesma quantidade de dados: 64 bits, se o valor é 1 ou -3,14 ou 1000000 ou 1e100 . A quantidade de tempo que leva para realizar uma operação nesses números não depende do valor real desses números, porque está sempre trabalhando na mesma quantidade de dados. Existe uma desvantagem em fazer as coisas dessa maneira, pois as duplas não podem representar com precisão todos os números (ou mesmo todos os números dentro de seu intervalo), mas elas podem se aproximar o suficiente para a maioria dos assuntos, e os tipos de coisas que o CSS faz não são numericamente exigente o suficiente para precisar de mais precisão do que isso. Combine isso com os benefícios da compatibilidade direta com o JavaScript e você terá uma forte justificativa para duplas.
Não é impossível que alguém possa implementar CSS usando uma codificação de tamanho variável para números. Se alguém utilizada uma codificação de comprimento variável, em seguida, comparando contra pequenos números seria menos dispendioso do que comparando contra grandes números, porque um grande número têm mais dados para trituração . Esses tipos de codificação podem ser mais precisos que binários, mas também são muito mais lentos, e para CSS em particular, os ganhos de precisão provavelmente não são suficientes para valer a pena o desempenho atingido. Eu ficaria muito surpreso ao saber que qualquer navegador fez as coisas dessa maneira.
Agora, em teoria, há uma exceção possível a tudo o que eu disse acima: comparar com zero é geralmente mais rápido do que comparar com outros números . Isso não ocorre porque o zero é curto (se esse foi o motivo, então 1 deve ser tão rápido, mas não é). É porque zero permite trapacear. É o único número em que todos os bits estão desativados; portanto, se você souber que um dos valores é zero, nem precisa olhar para o outro valor como um número: se algum dos bits estiver ativado, não será igual a zero e, em seguida, você só precisa olhar um bit para ver se é maior ou menor que zero.
fonte
Se esse código estivesse sendo interpretado toda vez que fosse executado, haveria uma diferença, pois levaria mais tempo para tokenizar e interpretar em
10000000000000
comparação com1000
. No entanto, esta é a primeira otimização óbvia dos intérpretes nesse caso: tokenize uma vez e interprete os tokens.fonte