Percebi que sempre usei int e doubles, não importa o quão pequeno ou grande o número precise ser. Portanto, em java, é mais eficiente usar byte
ou em short
vez de int
e em float
vez de double
?
Portanto, suponha que tenho um programa com muitos ints e duplos. Valeria a pena examinar e mudar meus ints para bytes ou shorts se eu soubesse que o número caberia?
Eu sei que o java não tem tipos não assinados, mas há algo extra que eu pudesse fazer se soubesse que o número seria positivo apenas?
Por eficiente, quero dizer principalmente processamento. Eu presumiria que o coletor de lixo seria muito mais rápido se todas as variáveis tivessem metade do tamanho e que os cálculos provavelmente seriam um pouco mais rápidos também. (Acho que, já que estou trabalhando no Android, preciso me preocupar um pouco com a memória RAM também)
(Eu presumo que o coletor de lixo lida apenas com objetos e não primitivos, mas ainda exclui todos os primitivos em objetos abandonados, certo?)
Eu tentei com um pequeno aplicativo Android que tenho, mas realmente não notei nenhuma diferença. (Embora eu não tenha medido nada "cientificamente".)
Estou errado em presumir que deveria ser mais rápido e eficiente? Eu odiaria mudar tudo em um programa enorme para descobrir que perdi meu tempo.
Valeria a pena fazer desde o início quando eu começar um novo projeto? (Quer dizer, acho que qualquer pequena parte ajudaria, mas então, novamente, se sim, por que não parece que alguém faz isso.)
fonte
Isso depende da implementação da JVM, bem como do hardware subjacente. A maioria dos hardwares modernos não busca bytes únicos da memória (ou mesmo do cache de primeiro nível), ou seja, usar os tipos primitivos menores geralmente não reduz o consumo de largura de banda da memória. Da mesma forma, a CPU moderna tem um tamanho de palavra de 64 bits. Eles podem realizar operações em menos bits, mas isso funciona descartando os bits extras, o que também não é mais rápido.
O único benefício é que tipos primitivos menores podem resultar em um layout de memória mais compacto, principalmente ao usar arrays. Isso economiza memória, o que pode melhorar a localidade de referência (reduzindo assim o número de perdas de cache) e reduzir a sobrecarga da coleta de lixo.
De modo geral, entretanto, usar os tipos primitivos menores não é mais rápido.
Para demonstrar isso, observe a seguinte referência:
que imprime em meu caderno um tanto antigo (adicionando espaços para ajustar colunas):
Como você pode ver, as diferenças de desempenho são mínimas. Otimizar algoritmos é muito mais importante do que a escolha do tipo primitivo.
fonte
short
ebyte
são mais eficientes quando armazenadas em matrizes grandes o suficiente para serem importantes (quanto maior a matriz, maior a diferença de eficiência; umbyte[2]
pode ser mais ou menos eficiente do que umint[2]
, mas não o suficiente para importar de qualquer maneira), mas os valores individuais são armazenados de forma mais eficiente comoint
.Usar em
byte
vez deint
pode aumentar o desempenho se você os usar em grande quantidade. Aqui está uma experiência:}
Esta aula testa a velocidade de criação de um novo
TestClass
. Cada teste faz isso 20 milhões de vezes e há 50 testes.Aqui está o TestClass:
Eu dirigi a
SpeedTest
aula e no final consegui isso:Agora estou transformando os ints em bytes no TestClass e executando-o novamente. Aqui está o resultado:
Eu acredito que este experimento mostra que se você está criando uma instância de uma grande quantidade de variáveis, usar byte em vez de int pode aumentar a eficiência
fonte
byte
podem ser >> mais lentas << do queint
.byte é geralmente considerado como 8 bits. curto é geralmente considerado como 16 bits.
Em um ambiente "puro", que não é java, já que todas as implementações de bytes e longs, shorts e outras coisas divertidas geralmente ficam escondidas de você, o byte faz melhor uso do espaço.
No entanto, seu computador provavelmente não é de 8 bits e provavelmente não é de 16 bits. isso significa que, para obter 16 ou 8 bits em particular, seria necessário recorrer a "artifícios" que perdem tempo para fingir que tem a capacidade de acessar esses tipos quando necessário.
Neste ponto, depende de como o hardware é implementado. No entanto, pelo que fui ensinado, a melhor velocidade é obtida armazenando coisas em blocos que sejam confortáveis para o uso da CPU. Um processador de 64 bits gosta de lidar com elementos de 64 bits e qualquer coisa menos do que isso geralmente requer "mágica de engenharia" para fingir que gosta de lidar com eles.
fonte
Uma das razões para short / byte / char ter menos desempenho é a falta de suporte direto para esses tipos de dados. Por suporte direto, isso significa que as especificações JVM não mencionam nenhum conjunto de instruções para esses tipos de dados. Instruções como armazenar, carregar, adicionar etc. têm versões para o tipo de dados int. Mas eles não têm versões para short / byte / char. Por exemplo, considere o código java abaixo:
O mesmo é convertido em código de máquina conforme abaixo.
Agora, considere alterar int para short conforme abaixo.
O código de máquina correspondente mudará da seguinte forma:
Como você pode observar, para manipular o tipo de dados curto, ele ainda está usando a versão de instrução do tipo de dados int e explicitamente convertendo int em curto quando necessário. Agora, devido a isso, o desempenho fica reduzido.
Agora, o motivo citado para não dar suporte direto como segue:
Citado da especificação JVM presente aqui (Página 58).
fonte
javac
compilador, e você não pode tirar nenhuma inferência confiável sobre o desempenho do programa na vida real. O compilador JIT compila esses bytecodes em instruções reais da máquina nativa e faz uma otimização bastante séria no processo. Se você deseja analisar o desempenho do código, é necessário examinar as instruções do código nativo. (E é complicado porque você precisa levar em consideração o comportamento de tempo de um pipeline x86_64 de vários estágios.)A diferença é quase imperceptível! É mais uma questão de design, adequação, uniformidade, hábito, etc ... Às vezes é só uma questão de gosto. Quando tudo o que você importa é que seu programa comece a funcionar e substituir um
float
por umint
não prejudicaria a correção, não vejo nenhuma vantagem em escolher um ou outro, a menos que você possa demonstrar que o uso de qualquer um dos tipos altera o desempenho. Ajustar o desempenho com base em tipos que são diferentes em 2 ou 3 bytes é realmente a última coisa com a qual você deve se preocupar; Donald Knuth disse uma vez: "A otimização prematura é a raiz de todos os males" (não tenho certeza se foi ele, edite se você tiver a resposta).fonte
float
não pode representar todos os inteiros e umaint
lata; nem podeint
representar qualquer valor não inteiro quefloat
possa. Ou seja, embora todos os valores int sejam um subconjunto de valores longos, um int não é um subconjunto de um float e um float não é um subconjunto de um int.substituting a float for a double
, se for o caso, o respondente deve editar a resposta. Se não, o respondente deve ficar de cabeça baixa de vergonha e voltar ao básico pelos motivos descritos por @pst e por muitos outros motivos.