पृष्ठभूमि
जैसा कि इस प्रश्न में कहा गया है , मैं लगातार ढेर अंतरिक्ष में डेटा की एक बड़ी (यानी, अबाधित) धारा को संसाधित करने के लिए स्केलाज़ 7 पुनरावृत्तियों का उपयोग कर रहा हूं।
मेरा कोड इस तरह दिखता है:
type ErrorOrT[M[+_], A] = EitherT[M, Throwable, A]
type ErrorOr[A] = ErrorOrT[IO, A]
def processChunk(c: Chunk, idx: Long): Result
def process(data: EnumeratorT[Chunk, ErrorOr]): IterateeT[Vector[(Chunk, Long)], ErrorOr, Vector[Result]] =
Iteratee.fold[Vector[(Chunk, Long)], ErrorOr, Vector[Result]](Nil) { (rs, vs) =>
rs ++ vs map {
case (c, i) => processChunk(c, i)
}
} &= (data.zipWithIndex mapE Iteratee.group(P))
समस्या
मुझे लगता है कि स्मृति रिसाव में चला गया है, लेकिन मैं यह जानने के लिए पर्याप्त नहीं हूं कि स्कैलाज / एफपी से पता चलता है कि बग स्कैलाज में है या मेरे कोड में है। सहज रूप से, मुझे उम्मीद है कि इस कोड को केवल P के Chunk
-size स्थान के लिए (के आदेश पर) की आवश्यकता होगी ।
नोट: मुझे एक समान प्रश्न मिला जिसमें एक OutOfMemoryError
का सामना किया गया था, लेकिन मेरा कोड उपयोग नहीं कर रहा है consume
।
परिक्षण
मैंने कोशिश की और समस्या को अलग करने के लिए कुछ परीक्षण चलाए। संक्षेप में, रिसाव केवल जब दोनों उठता प्रतीत होता है zipWithIndex
और group
किया जाता है।
// no zipping/grouping
scala> (i1 &= enumArrs(1 << 25, 128)).run.unsafePerformIO
res47: Long = 4294967296
// grouping only
scala> (i2 &= (enumArrs(1 << 25, 128) mapE Iteratee.group(4))).run.unsafePerformIO
res49: Long = 4294967296
// zipping and grouping
scala> (i3 &= (enumArrs(1 << 25, 128).zipWithIndex mapE Iteratee.group(4))).run.unsafePerformIO
java.lang.OutOfMemoryError: Java heap space
// zipping only
scala> (i4 &= (enumArrs(1 << 25, 128).zipWithIndex)).run.unsafePerformIO
res51: Long = 4294967296
// no zipping/grouping, larger arrays
scala> (i1 &= enumArrs(1 << 27, 128)).run.unsafePerformIO
res53: Long = 17179869184
// zipping only, larger arrays
scala> (i4 &= (enumArrs(1 << 27, 128).zipWithIndex)).run.unsafePerformIO
res54: Long = 17179869184
परीक्षणों के लिए कोड:
import scalaz.iteratee._, scalaz.effect.IO, scalaz.std.vector._
// define an enumerator that produces a stream of new, zero-filled arrays
def enumArrs(sz: Int, n: Int) =
Iteratee.enumIterator[Array[Int], IO](
Iterator.continually(Array.fill(sz)(0)).take(n))
// define an iteratee that consumes a stream of arrays
// and computes its length
val i1 = Iteratee.fold[Array[Int], IO, Long](0) {
(c, a) => c + a.length
}
// define an iteratee that consumes a grouped stream of arrays
// and computes its length
val i2 = Iteratee.fold[Vector[Array[Int]], IO, Long](0) {
(c, as) => c + as.map(_.length).sum
}
// define an iteratee that consumes a grouped/zipped stream of arrays
// and computes its length
val i3 = Iteratee.fold[Vector[(Array[Int], Long)], IO, Long](0) {
(c, vs) => c + vs.map(_._1.length).sum
}
// define an iteratee that consumes a zipped stream of arrays
// and computes its length
val i4 = Iteratee.fold[(Array[Int], Long), IO, Long](0) {
(c, v) => c + v._1.length
}
प्रशन
- क्या मेरे कोड में बग है?
- मैं यह काम कैसे कर सकता हूं?
-XX:+HeapDumpOnOutOfMemoryError
ग्रहण MAT Eclipse.org/mat के साथ डंप का विश्लेषण करने की कोशिश कर सकते हैं और यह देख सकते हैं कि सरणियों के लिए कोड की कौन सी रेखा पकड़ रही है।
var
काउंटर बनाए रखने के रूप में दोहरा सकते हैं।
Long
प्रति एकल इंडेक्स जोड़ने से एल्गोरिथ्म निरंतर से गैर-निरंतर हीप स्थान में बदल जाएगा? नॉन-जिपिंग संस्करण स्पष्ट रूप से निरंतर हीप स्पेस का उपयोग करता है, क्योंकि यह कई प्रक्रिया को "प्रोसेस" कर सकता है क्योंकि आप इंतजार करना चाहते हैं।