Por que o ES6 nativo promete mais lento e exige mais memória do que o bluebird?

185

Em este benchmark , o pacote leva 4 vezes mais tempo para ser concluído com promessas do ES6 em comparação com as promessas do Bluebird e usa 3,6 vezes mais memória.

Como uma biblioteca JavaScript pode ser muito mais rápida e leve do que a implementação nativa da v8 escrita em C? As promessas do Bluebird têm exatamente a mesma API que as promessas nativas do ES6 (além de vários métodos de utilidade extra).

A implementação nativa está apenas mal escrita ou há algum outro aspecto disso que esteja faltando?

    
por callum 10.04.2015 / 22:12
fonte

1 resposta

258

Autor do Bluebird aqui.

V8 promete que a implementação está escrita em JavaScript não C. JavaScript (incluindo o próprio do V8) é compilado para o código nativo. Além disso, o JavaScript escrito pelo usuário é otimizado, se possível (e vale a pena), antes de compilado para o código nativo. A implementação de promessas é algo que não se beneficiaria muito ou em nada de ser escrito em C, na verdade, só tornaria mais lento, porque tudo o que você está fazendo é manipular objetos JavaScript e comunicação.

A implementação do V8 simplesmente não é tão otimizada quanto o bluebird, mas para instâncias aloca arrays para manipuladores de promessas . Isso exige muita memória quando cada promessa também tem que alocar um par de matrizes (o benchmark cria promessas de 80k em geral, de modo que são 160k arrays não utilizados alocados). Na realidade, 99,99% dos casos de uso nunca ramificam uma promessa mais de uma vez, portanto, otimizar para esse caso comum gera grandes melhorias no uso da memória.

Mesmo se o V8 implementasse as mesmas otimizações do bluebird, ele ainda seria prejudicado pela especificação. O benchmark tem que usar new Promise (um anti-padrão no bluebird), pois não há outra maneira de criar uma promessa raiz no ES6. new Promise é uma maneira extremamente lenta de criar uma promessa, primeiro a função executora aloca um encerramento, em segundo lugar, é passado dois fechamentos separados como argumentos. Isso é 3 closures alocados por promessa, mas um fechamento já é um objeto mais caro do que uma promessa otimizada.

O Bluebird pode usar promisify , o que permite muitas otimizações e é uma maneira muito mais conveniente de consumir APIs de retorno de chamada e permite converter módulos inteiros em módulos baseados em promessa em uma linha ( promisifyAll(require('redis')); ).

    
por 14.04.2015 / 09:22
fonte