স্কালাজ z টি জিপউইথইন্ডেক্স / গোষ্ঠী গণনা সহ মেমরি ফাঁস এড়ানো


106

পটভূমি

এই প্রশ্নে উল্লিখিত হিসাবে , আমি ধ্রুবক স্তূপ স্থানে ডেটার একটি বৃহত্তর (অর্থাত্ আনবাউন্ডেড) প্রসেসটি প্রক্রিয়াকরণের জন্য স্কালাজ 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))

সমস্যাটি

আমি মনে করি কোনও স্মৃতি ফাঁস হয়ে গেছে তবে আমি স্ক্যালাজ / এফপি-র সাথে যথেষ্ট পরিমাণে পরিচিত নই যে বাগ স্ক্যালাজে আছে বা আমার কোডে আছে তা জানার জন্য। স্বজ্ঞাতভাবে, আমি এই কোডটি কেবলমাত্র (ক্রম অনুসারে) পি-পি - Chunkসাইজের স্থানের প্রয়োজন বলে আশা করি ।

দ্রষ্টব্য: আমি একটি অনুরূপ প্রশ্ন পেয়েছি যার মধ্যে একটি 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
}

প্রশ্নাবলি

  • বাগটি কি আমার কোডে আছে?
  • আমি কীভাবে এই কাজটি ধ্রুবক স্তূপ স্থানে করতে পারি?

6
আমি স্ক্যালাজে একটি সমস্যা হিসাবে এটি রিপোর্টিং শেষ করেছি
অ্যারন নভস্ট্রাপ 21

1
এটি কোনও মজাদার হবে না তবে আপনি অ্যারেতে কী রেখাঙ্কিত কোডটি ধরেছে তা দেখার জন্য -XX:+HeapDumpOnOutOfMemoryErrorগ্রহনটি ম্যাট গ্রহন সূত্র / ম্যাট সহ ডাম্পটিকে বিশ্লেষণ ও বিশ্লেষণ করতে পারেন।
huynhjl

10
@ হুইনজেল এফডাব্লুআইডাব্লু, আমি জেপ্রোফিলার এবং এমএটি উভয়ের সাথে স্তূপ বিশ্লেষণ করার চেষ্টা করেছি কিন্তু বেনাম ফাংশন ক্লাসের সমস্ত রেফারেন্স দিয়ে পুরোপুরি বিস্মৃত হতে পারিনি ইত্যাদি। স্কেলার এই ধরণের জিনিসটির জন্য সত্যই নিবেদিত সরঞ্জামের প্রয়োজন needs
অ্যারন নভস্ট্রাপ

যদি কোনও ফুটো না থাকে এবং এটি যে আপনি যা করছেন কেবল স্মৃতিশক্তি বর্ধমান পরিমাণে প্রয়োজন? আপনি varযেমন যান ঠিক তেমন কোনও কাউন্টার বজায় রেখে particular নির্দিষ্ট এফপি নির্মাণ ব্যতীত আপনি সহজেই জিপউইথইনডেক্সকে প্রতিলিপি করতে পারেন।
এজেকিয়েল ভিক্টর

@ ইজিকেলভিক্টর আমি নিশ্চিত না যে আমি মন্তব্যটি বুঝতে পেরেছি। আপনি পরামর্শ দিচ্ছেন যে Longপ্রতি অংশে একটি একক সূচক যুক্ত করা হলে অ্যালগরিদমকে ধ্রুবক থেকে অ-ধ্রুবক হিপ স্থানটিতে পরিবর্তন করবে? জিপবিহীন সংস্করণ পরিষ্কারভাবে ধ্রুবক হ্যাপ স্পেস ব্যবহার করে, কারণ এটি যতটা অপেক্ষা করতে চান তত বেশি অংশ "প্রক্রিয়া" করতে পারে।
অ্যারন নভস্ট্রাপ

উত্তর:


4

এটি পুরানো iterateeএপিআইয়ের সাথে আটকে থাকা যে কারও পক্ষে খুব কম সান্ত্বনা আসবে তবে আমি সম্প্রতি যাচাই করেছিলাম যে স্ক্যালাজ-স্ট্রিম এপিআইয়ের বিপরীতে একটি সমমানের পরীক্ষায় পাস হয় । এটি একটি নতুন স্ট্রিম প্রসেসিং এপিআই যা প্রতিস্থাপনের উদ্দেশ্যে iteratee

সম্পূর্ণতার জন্য, এখানে পরীক্ষার কোডটি রয়েছে:

// create a stream containing `n` arrays with `sz` Ints in each one
def streamArrs(sz: Int, n: Int): Process[Task, Array[Int]] =
  (Process emit Array.fill(sz)(0)).repeat take n

(streamArrs(1 << 25, 1 << 14).zipWithIndex 
      pipe process1.chunk(4) 
      pipe process1.fold(0L) {
    (c, vs) => c + vs.map(_._1.length.toLong).sum
  }).runLast.run

এটি nপ্যারামিটারের জন্য কোনও মান দিয়ে কাজ করা উচিত (আপনি যদি যথেষ্ট দীর্ঘ অপেক্ষা করতে চান তবে) - আমি 2 ^ 14 32MiB অ্যারে (অর্থাত্ সময়ের সাথে মোট বরাদ্দকৃত অর্ধেক টিআইবি) দিয়ে পরীক্ষা করেছি।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.