Eu montei alguns testes simples que renderizam uma imagem em uma tela. Um processa a partir de um IMG, enquanto o outro processa a partir de uma tela fora da tela. Você pode ver o código e os resultados aqui: http://jsperf.com/canvas-rendering/2
Na maioria dos navegadores, a renderização de uma imagem é muito mais rápida que a renderização de uma tela, exceto no Chrome, onde a situação é inversa. Alguém pode explicar o motivo das diferenças? Afinal, estamos renderizando os mesmos dados de pixel no mesmo destino.
html-canvas
alekop
fonte
fonte
Respostas:
OK, eu descobri. Quase. Na verdade, é bastante óbvio, e me sinto um pouco idiota por não perceber isso imediatamente. Quando você chama
drawImage(src, 0, 0)
sem especificar largura / altura, ela desenha toda a região src, que neste caso é muito maior (a tela é 320x420 versus a img em 185x70). Portanto, no caso da tela, o navegador está fazendo muito mais trabalho, o que explica o desempenho mais lento. Ainda estou intrigado com a pontuação mais alta do Chrome com o src maior.Publiquei uma versão atualizada que usa as mesmas regiões e as diferenças são muito mais próximas. http://jsperf.com/canvas-rendering/5
Ainda não consigo explicar por que há uma diferença, mas agora é pequena o suficiente para que eu realmente não me importo.
fonte
É provável que o Chrome use a aceleração de hardware.
Crie uma tela de 240 x 240 e execute sua experiência no Chrome. Crie uma tela de 300 x 300 e faça-a novamente. A tela maior que eu espero ser mais rápida, devido ao fato de a aceleração do hardware aparecer após 256x256 e o chrome usar software quando os tamanhos forem menores.
Também vale ressaltar que -webkit-transform: translateZ (0) desativa a aceleração de hardware.
Eu não testei nenhuma das opções acima; Eu só sei disso devido ao fato de um dos engenheiros do Chrome ter comentado um bug relatado no Chrome quando você ultrapassa o limite de hardware e software, redimensionando dinamicamente a tela de maior para menor que o limite de 256x256 ou vice-versa. A solução para esse bug foi desativar a aceleração usando o translateZ, como mencionado acima.
No meu caso, simplesmente não permiti que os usuários redimensionassem menos de 256x256.
fonte
Às vezes, as imagens podem ser carregadas na memória da GPU e na tela da memória do host. Nesse caso, quando você desenha da imagem para a tela, os dados da imagem devem ser copiados primeiro para hospedar a memória e depois para a tela.
Percebi esse tipo de comportamento com o Chrome, quando eu escrevia um projeto que carrega mais de 100 milhões de imagens de pixel e, em seguida, lê partes delas em telas pequenas de 256x256 ( http://elhigu.github.io/canvas-image-tiles/ ).
Nesse projeto, se eu desenhasse diretamente da tag de imagem para a tela no Chrome, a memória sempre aumentava para ~ 1,5 GB quando o desenho era iniciado e, quando o desenho terminava, a memória era liberada novamente, mesmo a imagem de origem de 250 megapixels era mostrada o tempo todo na página.
Corrigi o problema gravando uma vez a imagem em tela grande (mesmo tamanho da imagem) e desenhando uma tela menor a partir daí (também joguei a imagem fora depois de convertê-la em tela).
fonte
Não posso explicar as diferenças, mas eu discordo de
Se você observar os resultados no js.pref, as diferenças no chrome são bastante sutis. Eu ficaria com apenas renderização de uma imagem, quando possível.
fonte
O tamanho da imagem é 185 * 70, mas criamos uma tela com tamanho. Acho que isso desperdiçará um pouco de desempenho. Por isso, defino o tamanho da tela fora da tela igual à imagem. E a diferença está mais próxima.
http://jsperf.com/canvas-rendering/60
fonte