2011-08-17 20 views
18

Sé que debe andar ligeramente al hacer llamadas recursivas a funciones en JavaScript porque su segunda llamada podría ser hasta 10 veces más lenta.Llamar a función recursiva en JavaScript

Eloquent JavaScript estados:

Hay un problema importante: En la mayoría de las implementaciones de JavaScript, esta segunda versión es aproximadamente 10 veces más lenta que la primera. En JavaScript, ejecutar un bucle simple es mucho más barato que llamar a una función varias veces.

John Resig incluso dice que esto es un problema en la publicación this.

Mi pregunta es: ¿Por qué es tan ineficiente utilizar la recursión? ¿Es solo la forma en que se construye un motor en particular? ¿Alguna vez veremos un momento en JavaScript donde este no sea el caso?

+1

Supongo que es un alcance: P Gran pregunta, tengo curiosidad por lo que responden es! – Pelshoff

+4

La sobrecarga de llamada de función es simplemente mayor que la del control de bucle; eso es cierto en casi cualquier lenguaje de programación. Hay mucho más que hacer al llamar una función: asignar e inicializar un nuevo alcance, guardar la dirección de retorno, calcular los parámetros, etc. Tenga en cuenta que los intérpretes de JavaScript se han acelerado a un ritmo muy rápido, por lo que las sugerencias de rendimiento en un 3 una publicación (o libro) de blog de un año debe ser cuestionada. – Pointy

+1

"porque su segunda llamada podría ser hasta 10 veces más lenta" Eso no es lo que dice el texto. Dice que la segunda versión del código es 10 veces más lenta. –

Respuesta

11

Las llamadas a funciones son simplemente más costosas que un simple bucle debido a todos los gastos generales de cambiar la pila y configurar un nuevo contexto, y así sucesivamente. Para que la recursividad sea muy eficiente, un lenguaje debe admitir alguna forma de eliminación de llamadas de cola, lo que básicamente significa transformar ciertos tipos de funciones recursivas en bucles. Los lenguajes funcionales como OCaml, Haskell y Scheme hacen esto, pero ninguna implementación de JavaScript de la que yo tenga conocimiento lo hace (solo sería marginalmente útil a menos que todos lo hicieran, así que tal vez tengamos un problema con los filósofos del comedor).

+5

ES6 debe tener optimización de la cola de llamadas. [Llamadas de cola adecuadas] (http://wiki.ecmascript.org/doku.php?id=harmony:proper_tail_calls) – Raynos

3

Esta es solo una forma en que los motores JS en particular que usan los navegadores están construidos, sí. Sin la eliminación de la llamada de cola, debe crear un nuevo marco de pila cada vez que recurse, mientras que con un bucle solo se establece el contador del programa nuevamente al inicio. Scheme, por ejemplo, tiene esto como parte de la especificación del lenguaje, por lo que puede utilizar la recursión de esta manera sin preocuparse por el rendimiento.

https://bugzilla.mozilla.org/show_bug.cgi?id=445363 indica que se está progresando en Firefox (y Brendan Eich habla aquí acerca de que posiblemente se haya convertido en parte de las especificaciones de ECMAScript), pero no creo que ninguno de los navegadores actuales lo haya implementado todavía.

Cuestiones relacionadas