https://kotlinlang.org logo
#coroutines
Title
# coroutines
j

Joey Heck

04/05/2018, 6:42 PM
Last night our meetup topic was Coroutines and I wanted to implement them in a json parse, but it's not as fast as I expected
Copy code
val gson = GsonBuilder().create()
val jsonArray: JSONArray = responseJsonObject.getJSONArray("Value")

val parsedItemArray = List<Deferred<Item>>(jsonArray.length()) {
    async { gson.fromJson(jsonArray.get(it).toString(), Item::class.java) }
}

runBlocking {
    parsedItemArray .forEach { defered ->
        val item = defered.await()
    }
}
So I'm parsing an array of json objects in a JSON array using gson into a list of Deferreds. I call the parsing in an async, then I wait until they are all done. I call a timestamp before and after it's done the same code without coroutines runs faster
Copy code
val gson = GsonBuilder().create()
val jsonArray: JSONArray = responseJsonObject.getJSONArray("Value")

val parsedItemArray = List<Item>(jsonArray.length()) {
    gson.fromJson(jsonArray.get(it).toString(), Item::class.java)
}
I was using a parallel class (found on stack overflow) previously with much better results
Copy code
object Parallel {

    private val iCPU = Runtime.getRuntime().availableProcessors()

    interface LoopBody<T> {
        fun run(i: T)
    }

    fun For(start: Int, stop: Int, loopBody: LoopBody<Int>) {
        val executor = Executors.newFixedThreadPool(iCPU)
        val futures = LinkedList<Future<*>>()

        for (i in start until stop) {
            val future = executor.submit { loopBody.run(i) }
            futures.add(future)
        }

        for (f in futures) {
            try {
                f.get()
            } catch (e: InterruptedException) {
            } catch (e: ExecutionException) {
            }

        }

        executor.shutdown()
    }
}
I call it with this
Copy code
val gson = GsonBuilder().create()
val jsonArray: JSONArray = responseJsonObject.getJSONArray("Value")

val parsedItemArray = arrayOfNulls<Item>(jsonArray.length())

Parallel.For(0, jsonArray.length(), object : Parallel.LoopBody<Int> {
	override fun run(i: Int) {
		parsedItemArray[i] = gson.fromJson(jsonArray.get(i).toString(), Item::class.java)
	}
})
g

groostav

04/05/2018, 6:47 PM
in your original code, have you tried specifying the same
executor
as a parameter in the
async
block? IE:
Copy code
val parsedItemArray = ... {
    async(executor.asCoroutineDispatcher) { ...
}
I agree it should be faster
by default you should be getting the Common Pool, IE a Fork-Join pool... unless this is an android java 6 thing?
Also, your
List
factory, is it using a linked list?
3 Views