Ei, descobri que a otimização do Dubbo não parece completa o suficiente? , Lembre-se de uma experiência de entrevista do post Java R&D da Ant Financial

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

Bom cara, rodei várias vezes, isso tudo é muito melhor do que if + switch, então todo o código-fonte deve ser alterado para if else, você pode ver que a taxa de transferência é alta e não é tão boa quanto se agora Depois por um tempo, o interruptor parece um pouco indefinido.

Alterei o valor gerado por state para random novamente e executei novamente para ver o resultado:

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

Eu executei isso muitas vezes e a taxa de transferência de if é a mais alta. Por que esse if inteiro é o melhor.

Descompilar if e switch

==================================================== =================================

Na minha opinião, essa opção deve ser melhor do que se, independentemente da previsão de ramificação da CPU, quando for o caso do ponto de vista do bytecode, vamos dar uma olhada nos bytecodes gerados por cada um.

Primeiro, observe a descompilação do switch e intercepte as partes principais.

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

Ou seja, o switch gera um switch de tabela. Após o getstatic acima obter o valor, ele pode verificar diretamente a tabela de acordo com o índice e, em seguida, pular para a linha correspondente para execução, ou seja, a complexidade de tempo é O( 1).

Por exemplo, se o valor for 1, pulará diretamente para executar a linha 64, se for 4, pulará diretamente para a linha 100.

Existem alguns pequenos detalhes sobre o switch. Quando os valores em swtich são descontínuos e têm um grande intervalo, o lookupwitch é gerado. De acordo com a declaração on-line, é uma consulta binária (não verifiquei), e a complexidade do tempo é O(logn), não baseado diretamente no índice, acho que o lookup gerado deveria ser dividido em dois, pois é ordenado por valor.

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

Além disso, quando os valores no switch são descontínuos, mas o intervalo é relativamente pequeno, o tableswtich ainda será gerado, mas preenchido com alguns valores. Por exemplo, neste exemplo, os valores no meu switch são 1, 3, 5 , 7 e 9, e preenche automaticamente 2 , 4, 6 e 8, todos se referem à linha ignorada por padrão.

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

Vejamos o resultado da descompilação do if novamente:

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

Pode-se ver que o if irá retirar a variável e compará-la com a condição todas as vezes, enquanto o switch irá procurar na tabela e pular para a linha correta depois de pegar a variável uma vez. Deste ponto de vista, a eficiência do switch deve ser melhor do que se. Claro, se o if passar no primeiro julgamento, ele irá diretamente, e os próximos julgamentos não serão executados.

Portanto, do ponto de vista do bytecode gerado, a eficiência do switch deve ser maior que a do if, mas do ponto de vista dos resultados do teste, a eficiência do if é maior do que a do switch. Seja um estado gerado aleatoriamente ou 99,99% de é o mesmo estado no caso de.

Em primeiro lugar, a otimização da previsão de desvio da CPU é afirmativa. Se ainda é melhor do que mudar em casos aleatórios, não sei por quê. Pode ser a operação de otimização feita pelo JIT ou o sucesso da previsão de desvio em casos aleatórios. benefício supera a falha em prever?

Será que meus valores de enumeração são muito poucos para refletir o efeito da troca? No entanto, o switch não deve ser mais fraco do que em situações aleatórias. Adicionei 7 valores de enumeração e testei novamente com um total de 12 valores. Os resultados são os seguintes:

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

Parece que a distância foi encurtada, eu vi um show, então recitei 26 letras, e pra falar a verdade, ainda cantei as letras datilografadas.

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

Depois de expandir o número de filiais, outra onda de testes foi realizada. Desta vez, o swtich está à altura do desafio e finalmente está mais forte do que if.

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

Digressão: vejo que há comparações entre if e switch na Internet. O resultado da comparação é que switch é melhor do que if. Em primeiro lugar, jmh não está escrito corretamente. Uma constante é definida para testar if e switch, e o resultado do método de teste é escrito sem consumo. Não sei como esse código será otimizado pelo JIT. Depois de escrever dezenas de linhas, pode ser otimizado diretamente para retornar um determinado valor.

Resuma os resultados do teste

==================================================== ============================

Depois de comparar tantos, vamos resumir.

Em primeiro lugar, o hot branch é extraído do switch e julgado independentemente por if, fazendo pleno uso da conveniência trazida pela previsão de branch da CPU é realmente melhor do que swtich puro. De nossos resultados de teste de código, a taxa de transferência é aproximadamente duas vezes maior.

No caso do hot branch, o throughput é melhorado ainda mais quando é alterado para julgamento if puro em vez de if + swtich. É 3,3 vezes de switch puro e 1,6 vezes de if + switch.

No caso de ramificação aleatória, a diferença entre os três não é muito grande, mas o caso do if puro é o melhor.

Mas do ponto de vista do bytecode, a eficiência do mecanismo de comutação deve ser maior, seja O(1) ou O(logn), mas não é do ponto de vista dos resultados do teste.

No caso de menos condições de seleção, se é melhor que trocar. Não sei porque. Pode ser que o consumo de consulta na tabela seja maior que o benefício no caso de menos valores? Quem souber pode deixar uma mensagem no final do artigo.

No caso de muitas condições de seleção, mudar é melhor do que se. Não testei mais nenhum valor de seleção. Se você estiver interessado, pode testar você mesmo, mas a tendência é assim.

Previsão de ramificação da CPU

==================================================== ============================

Em seguida, vamos dar uma olhada em como essa previsão de ramificação é feita, por que existe uma previsão de ramificação, mas antes de falarmos sobre a previsão de ramificação, precisamos apresentar o pipeline de instruções (pipeline de instrução), que é o pipeline dos microprocessadores modernos.

A essência da CPU é buscar e executar instruções, e vamos dar uma olhada nas cinco principais etapas de buscar e executar instruções, que são buscar instruções (IF), decodificar instruções (ID), executar instruções (EX), acesso à memória (MEM) e escrevendo os resultados (WB) e, em seguida, olhe para uma imagem na Wikipedia.

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

Claro, pode haver mais etapas. De qualquer forma, isso significa que muitas etapas precisam ser experimentadas, então uma execução pode ser dividida em várias etapas, tantas etapas podem ser paralelizadas para melhorar a eficiência do processamento.

Portanto, o pipelining de instruções é uma tentativa de manter todas as partes do processador ocupadas com algumas instruções, dividindo as instruções recebidas em uma série de etapas sequenciais a serem executadas por diferentes unidades de processador, com diferentes partes de instrução processadas em paralelo.

Assim como a linha de montagem em nossa fábrica, quando os pés do meu Ultraman são montados, os pés do próximo Ultraman serão montados imediatamente. Não vou esperar o último Ultraman ser montado para montar o próximo Ultraman.

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

Claro, não é tão rígido. Não significa necessariamente execução sequencial. Algumas instruções estão esperando e as instruções seguintes não dependem dos resultados anteriores, portanto podem ser executadas antecipadamente. Isso é chamado de execução fora de ordem .

Vamos voltar à nossa previsão de ramificação.

Assim como a nossa vida, esse código sempre se depara com uma escolha. Só depois de fazer uma escolha é que podemos saber como ir. Mas, na verdade, descobriu-se que esse código geralmente faz a mesma escolha, então criei uma previsão de ramificação . dispositivo, deixe-o prever a tendência e executar as instruções ao longo do caminho com antecedência.

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

E se a previsão estiver errada? Isso é diferente da nossa vida. Pode jogar fora todos os resultados da execução anterior e fazer de novo, mas também tem um impacto, ou seja, quanto mais fundo o pipeline, mais erros e mais desperdício. O atraso na previsão errada é 10 a 20 ciclos de clock, então ainda há efeitos colaterais.

Simplificando, o preditor de desvio é usado para prever as instruções que serão saltadas e executadas no futuro, e depois pré-executadas, para que o resultado possa ser obtido diretamente quando for realmente necessário, o que melhora a eficiência.

A previsão de ramificação é dividida em vários tipos de métodos de previsão, incluindo previsão estática, previsão dinâmica, previsão aleatória, etc. Existem 16 tipos da Wikipédia.

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

Deixe-me falar brevemente sobre os três tipos que mencionei. A previsão estática é atordoada, assim como as perguntas de múltipla escolha em inglês da Mongólia. Não me importa quais perguntas você tem, escolherei A, o que significa que preverá uma tendência, vá apresente-se indomavelmente e seja simples e rude.

A previsão dinâmica determinará a direção da previsão com base nos registros históricos. Por exemplo, se as seleções anteriores forem verdadeiras, executarei as instruções. Se as últimas vezes forem alteradas para falsas, tornarei-me falsa. Essas as instruções executadas realmente usam o princípio da localidade.

Você pode saber a previsão aleatória apenas olhando para o nome. Esta é outra forma de perguntas de múltipla escolha em inglês mongol. Você pode adivinhar às cegas e escolher uma direção aleatória para executar diretamente.

Há muitos mais que não vou listar um por um. Você está interessado em pesquisar por conta própria. A propósito, em 2018, o projeto zero do Google e outros pesquisadores anunciaram uma vulnerabilidade de segurança catastrófica chamada Spectre, que pode usar a previsão de ramificação da CPU A execução de vazamentos de informações confidenciais não será expandida aqui e um link será anexado no final do artigo.

Mais tarde, houve outro ataque chamado BranchScope, que também usava execução preditiva, então sempre que um novo gadget for lançado, sempre trará prós e contras.

Até agora sabemos o que são pipeline de instrução e predição de desvio, e por que o Dubbo é tão otimizado, mas o artigo ainda não acabou, também quero mencionar essa pergunta muito famosa no stackoverflow, veja o número.

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

Por que é mais rápido processar arrays ordenados do que arrays não ordenados?

==================================================== ====================================

Essa questão foi levantada no início daquele blog. Obviamente, isso também está relacionado à previsão de ramificação. Agora que você viu, vamos analisá-la novamente. Você pode responder a essa pergunta primeiro em sua mente. Afinal, todos nós sabemos o responda. , Veja se o pensamento está claro.

É o seguinte código, o loop é mais rápido depois que o array é classificado.

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

Então os grandes mestres de todas as esferas da vida apareceram, vamos dar uma olhada no que os primeiros mestres de louvor disseram.

Assim que abriu a boca, atingiu diretamente o ponto vital.

Você é uma vítima de falha na previsão de ramificação.

Imediatamente após a foto acima, parece um driver antigo.

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

Ele disse que vamos voltar ao século 19, uma época em que a comunicação de longa distância era impossível e o rádio não era popular. Se você fosse um manobrista em um cruzamento ferroviário, como saberia para que lado virar quando o trem se aproximasse? ?

Parar e reiniciar o trem consome muita energia. Toda vez que você para em uma bifurcação, você pergunta a ele, onde você está indo, e então vira a estrada, e reiniciar é demorado. O que devo fazer? Adivinhar!

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

Se você adivinhar corretamente, o trem não precisa parar, apenas continue. Se você adivinhar errado, pare e dê ré, depois mude de faixa e dirija novamente.

Então cabe a você adivinhar! Experimente e transforme sua bicicleta em uma motocicleta.

Em seguida, o chefe apontou o código de montagem correspondente ao código-chave, ou seja, a instrução de salto, que corresponde à bifurcação do trem, e é hora de escolher uma estrada.

Ei, descobri que a otimização do Dubbo não parece completa o suficiente?

Não vou analisar depois, todos devem saber que após o array ordenado ser executado até o valor ser maior que 128, todos eles devem ser maiores que 128, então o resultado de cada previsão de desvio está correto! Portanto, a eficiência de execução é muito alta.

A matriz não classificada está fora de ordem, muitas vezes a previsão estará errada e, se a previsão estiver errada, o pipeline de instruções deve ser esvaziado e, em seguida, será feito novamente. Claro, a velocidade será lenta.

Portanto, o chefe disse que você é vítima de uma previsão incorreta da ramificação neste tópico.

Acho que você gosta

Origin blog.csdn.net/m0_65484000/article/details/122007809
Recomendado
Clasificación