2010-11-02 34 views
5

Comenzó cuando leí el ensayo de Guido van Rossum An Optimization Anecdote.¿Por qué es tan lento el array.map (String.fromCharCode)?

La decisión de intentar hacer lo mismo en JavaScript, lo cronometré los siguientes:

numbers.map(function(x){ return String.fromCharCode(x); }); 

Esto fue bastante rápido ya, pero ¿por qué no elimina por completo la función anónima y pasar directamente a String.fromCharCode mapa():

numbers.map(String.fromCharCode); 

lo cronometré y ... ... esto era ~ 100 veces más lento que la versión anterior. ¿Cómo?

De alguna manera, pasar esta función nativa directamente a Array.map() es mucho más lento que envolverlo dentro de otra función y pasarlo a Array.map().

  • No es específico del navegador: probado en Chrome, Firefox y Opera.

  • No es específico de map(): intenté porEach(), que se comportó de manera similar.

  • No es específico de las funciones integradas: intenté con Math.round() y Math.sin() - con estos resultados fueron los que cabría esperar: pasar la función a Array.map() directamente fue un poco un poco más rápido que usar la función anónima intermedia.

Parece que el problema es con String.fromCharCode específicamente.

¿Qué está pasando aquí?

PS. Originalmente planteé esta pregunta en Hacker News thread, pero como el artículo relacionado es sobre Python, pensé que obtendría más exposición a los desarrolladores de JavaScript cuando se publicara aquí. Perdón por la publicación cruzada.

Respuesta

5

Encontré la solución por mi cuenta.

El problema es que String.fromCharCode() toma varios argumentos y Array.map() también pasa múltiples argumentos a la devolución de llamada. Por lo tanto el código:

numbers.map(String.fromCharCode); 

es en realidad equivalente a:

numbers.map(function(x, y, z){ return String.fromCharCode(x, y, z); }); 

de la que es bastante evidente por qué es tan lento. Además, también tiene errores.

+1

Estaba a punto de publicar esta misma respuesta. El resultado esperado es diferente porque 'String.fromCharCode' construye la cadena devuelta a partir de todos los argumentos pasados ​​(en este caso, los primeros 2 argumentos pasados ​​porque el tercero no es un número). –

Cuestiones relacionadas