OOM in CoroutineWorker when doing Bitmap operations

74 Views Asked by At

I am trying to run some work for a set of files (~2000), and I need to decode some, so it takes a lot of memory. If I am 'doing work' like that:

override suspend fun doWork(): Result {
     (0...2000).forEach { i ->
         analyze(uris[i])
       }
     return Result.success()
}

fun analyze(uri) {
   val bitmap = decodeBitmap(uri)
 .onSuccess{
      apply color filer()
  }.onSuccess {
   save bitmap to file system() 
  }
 }

I am getting OOM in 10 seconds, because decoding, color filtering and saving are async, and e.g. there are 100 bitmaps decoded, but only 10 are color filtered, and memory is overflowed with bitmaps, and then I am getting OOM.

Is there any way to run async operations in Worker without returning? I reworked all flow to recursion, but it's seems to be impossible to run recursion in Worker. Maybe there are some smart suspend way?

1

There are 1 best solutions below

2
levi On

You need to make analyze a suspend function, that suspends execution while waiting for the async request to complete. Currently, analyze returns immediately, which means the 2000 files are being decoded in parallel.

You can use suspendCoroutine to achieve that.

suspend fun analyze() = suspendCoroutine { continuation ->
      val bitmap = decodeBitmap(uri)
 .onSuccess{
     etc...
  }.onSuccess {
      continuation.resume()
  }
}