2009-08-30 26 views
5

La ejecución del retraso es casi siempre una bendición. Pero luego hay casos en los que es un problema y recurres a "buscar" (en Nhibernate) para buscarlo ansiosamente.¿Cuándo la evaluación perezosa no es útil?

¿Conoces situaciones prácticas cuando la evaluación perezosa puede morderte ...?

Respuesta

0

Los recursos de carga diferida implican un viaje de ida y vuelta entre el solicitante y la fuente para cada carga. En el caso de NHibernate, esto significa a desde la aplicación a la base de datos (que a menudo se encuentra en un servidor diferente).

A menudo hay gastos indirectos asociados con cada viaje (sin duda hay para NHibernate o cualquier otra consulta DB).

Si sabe que necesitará todos o una parte sustancial de los datos, es mejor que lo haga de una sola vez y solo incurra en los gastos generales una vez.

Un ejemplo clásico es cuando necesita extraer una lista de objetos para rellenar un cuadro combinado (a menudo estos serán objetos de configuración). La carga lenta volverá a la base de datos cada vez que agregue un miembro de la lista al cuadro combinado. Puesto que está poniendo toda la lista en el cuadro combinado, incurriría en una gran cantidad de sobrecarga adicional para recuperar cada objeto.

0

También puede ser un problema con la experiencia del usuario de su programa. La gente estará feliz de esperar 5 segundos cuando se muestre un banner en la pantalla durante la carga de la aplicación, pero desprecian tener que esperar 0,25 segundos cuando están escribiendo algo en un cuadro de texto. Si la cantidad de tiempo que lleva cargar sus datos ansiosamente no es tan larga, puede considerar hacerlo en algún momento del flujo de trabajo donde la gente acepta un retraso (como la carga de aplicaciones, ventana emergente, presionar botones).

3

La evaluación diferida no es útil en situaciones donde el rendimiento es crítico y se debe evaluar un valor siempre. En estos casos, es mejor que simplemente evalúes el valor y lo hagas con él, ya que la sobrecarga de la evaluación perezosa se desperdiciará.

+0

La evaluación perezosa es una forma de obtener el rendimiento. – Zorf

+5

Incorrecto. Si debe evaluar la respuesta, la sobrecarga adicional para la evaluación perezosa crea un costo sin beneficio. – vy32

+0

vy32 es correcto. Por ejemplo, si tiene una lista de objetos que se muestran en una lista en un dispositivo móvil, la vista se creará en el momento en que los elementos de la lista aparezcan en la pantalla. Si algunos valores que se muestran en la lista tienen que cargarse vagamente, la lista se tambaleará y se demorará porque los nuevos elementos de lista no se pueden llenar con la suficiente rapidez. – Janusz

0

La evaluación diferida no es útil cuando no desea almacenar valor, solo úselo. Pero esto depende de la implementación del evaluador perezoso. Algunos sistemas (como Haskell) pueden decir si un valor se usará nuevamente. Algunos otros no pueden y pueden causar fugas.

2

La evaluación diferida no es útil cuando la evaluación puede tener efectos secundarios. Esa es la única razón y es por eso que solo los lenguajes puramente funcionales lo tienen. Si las expresiones pueden tener efectos secundarios que deben ocurrir en un orden determinado, no puede tenerlo.

Aparte de eso, la evaluación perezosa solo mejora el rendimiento, ese es su objetivo principal. Y es por eso que algunos idiomas prohíben los efectos colaterales, para obtener una evaluación perezosa para ese compromiso, otro buen efecto es que las estructuras de control pueden ser funciones regulares.

2

Un ejemplo de pereza causando problemas extraños (que me pasó hoy, en Haskell):

import System.IO 

main = do 
    content <- readFile "foo.txt" 
    writeFile "foo.txt" content 

Esto arroja el siguiente error cuando se compila & ejecutados:

foo.txt: openFile: resource busy (file is locked) 

Lo que pensé que lo haría do: Abra el archivo foo.txt, lea el contenido, ciérrelo de nuevo. Luego ábralo para escribir, escriba el contenido y ciérrelo nuevamente.

Lo que realmente hizo: "Ah, algo de contenido. Probablemente lo lea más adelante cuando realmente lo necesitemos". Luego abra "foo.txt" para escribir. Comience a escribir contenido ... bien, ahora necesitamos el contenido. Abre foo.txt para leer - ¡bam!

Sé que es trivial de arreglar, pero es difícil de encontrar si no sabes dónde buscar.

+1

Este es un problema causado específicamente por la E/S perezosa, en lugar de una evaluación perezosa en general. Lazy I/O es realmente bastante peligrosa y contra el espíritu de la programación funcional, ya que da efectos colaterales a funciones que deberían ser puras (es decir, evaluar una cadena hace que los datos se lean del disco, ¡un efecto secundario!), Lo que lleva a problemas como este, y este también: http://stackoverflow.com/questions/2981582/haskell-lazy-io-and-closing-files Pero ciertamente puede tener una evaluación lenta sin E/S perezosa, de hecho, tal parece ser la dirección actual de Haskell. – Jesse

+0

¡Este es un buen ejemplo! – vy32

4

No se puede hacer una reducción (por ejemplo, un pliegue) en datos de entrada en espacio constante con evaluación diferida, ya que la evaluación diferida de cada paso de reducción da como resultado una complejidad de espacio lineal. En su lugar, debe forzar la evaluación del resultado de cada paso de reducción para mantener constante el uso del espacio.

Por ejemplo, hashing un archivo en Haskell. Puede que tengas buenas intenciones y leer el archivo de entrada perezosamente por partes, añadiendo cada fragmento al resumen, pero a tus espaldas Haskell está haciendo un procesador por cada fragmento que agregues al resumen, dejando el archivo completo en la memoria estos thunk hasta que el resumen resultante sea evaluado. ¡Ay!

Ver último comentario aquí: Haskell lazy I/O and closing files

Cuestiones relacionadas