2011-12-19 8 views
12

Según tengo entendido, Stream conserva los elementos evaluados recientemente. Supongo que no retiene todos los elementos evaluados (no es factible), por lo que probablemente utiliza algún "caché" interno.Flujos de Scala y su uso de memoria

¿Es correcto? ¿Puedo controlar el tamaño y las políticas de este caché?

+1

No debe pensar en 'Stream's como' Iterator's, sino más bien como 'List's cuya evaluación se puede retrasar. [Esta pregunta y sus respuestas] (http://stackoverflow.com/questions/1527962/difference-between-iterator-and-stream-in-scala) pueden ayudar. – Philippe

Respuesta

6

El objeto Stream retiene todas las referencias que se han evaluado/accedido hasta el momento. Stream funciona como List. Todos los elementos a los que se puede acceder desde una referencia retenida y a los que ya se ha accedido al menos una vez, no serán recolectados.

Así que, básicamente, sus punteros en la secuencia y lo que ha evaluado hasta ahora definen qué se almacenará en caché.

+0

Por lo tanto, 'stream' no tiene una memoria caché_limitada_ para almacenar sus elementos. Suena como un enfoque que consume mucha memoria ... – Michael

+1

Es por eso que _never_ debe mantener una referencia a las transmisiones. Siempre defínalos usando 'def'. Consulte también http://stackoverflow.com/questions/12486762/scala-tail-recursive-stream-processor-function-defined-in-trait-holds-reference y http://stackoverflow.com/questions/12529697/how- to-write-non-leaking-tail-recursive-function-using-stream-cons-in-scala – ron

12

Las transmisiones son como listas que generan sus miembros a medida que se requieren. Una vez que se ha generado un elemento, se retiene en la secuencia y se reutiliza.

Por ejemplo:

lazy val naturals: Stream[Int] = Stream.cons(0, naturals.map{_ + 1}) 

le dará una corriente de los números naturales. Si llamo

naturals(5) 

generará elementos 0-5 y volver 5, a continuación, si yo llamo

naturals(8) 

Se reutilizará los primeros 6 elementos y generar 3 más.

Si le preocupa el uso de la memoria, puede usar Stream.drop(num) para generar una nueva secuencia con num elementos eliminados desde el principio, lo que permite que los elementos truncados se recolecten con la antigua. Por ejemplo:

naturals(5) //returns 5 
val truncated = naturals.drop(4) 
truncated(5) //returns 9 
+6

Sin embargo, mientras 'naturals' todavía esté apuntando a la cabecera de la secuencia, esos primeros cinco elementos no serán basura recogido. –