Estoy escribiendo una aplicación de fondo en Kotlin.
Para acelerar las cosas, actualmente confío en RxKotlin en el servidor para realizar la ejecución paralela de tareas de E / S, como llamadas a bases de datos y llamadas a API. El código generalmente se ve así.
val singleResult1 = Single.fromCallable{
database.get(....)
}.io()
val singleResult2 = Single.fromCallable{
database.update(....)
}.io()
Single.zip(singleResult1, singleResult2){ result1: Result1, result2: Result2 ->
....
}
.flatMap{
//other RX calls
}
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.computation())
.blockingGet()
Sin embargo, dado que no funciona realmente funciona con múltiples eventos (solo singles), Rx se siente un poco desordenado y solo agrega un montón de repeticiones (también causa complicaciones si quiero devolver un valor nulo y a veces podría estropear el seguimiento de la pila )
Estoy pensando en eliminar Rx y usar Executors
(o hilos) para el paralelismo insteada. ¿Hay alguna consideración de rendimiento a considerar aquí?
Ejemplo en lo que estoy pensando:
fun <T> waitAll(tasks: List<Callable<T>>, threadCount: Int = -1): List<T> {
val threads = if (threadCount == -1) tasks.size else threadCount
val executor = Executors.newFixedThreadPool(threads)
val results = executor.invokeAll(tasks).map {
it.get()
}
executor.shutdown()
return results
}
Y usándolo así:
waitAll(listOf(callable1, callable2))
¿O tal vez usando hilos regulares y unirlos?
threads.forEach{
it.start()
}
threads.forEach{
it.join()
}
¿O por qué no corrientes?
listOf(callable1,callable2)
.parallelStream()
.map{it.call()}
.collect(Collectors.toList())
fuente
Respuestas:
KotlinRx en sí mismo usa ejecutores, excepto que tiene dos grupos de subprocesos creados previamente
Schedulers.io()
(sin límites) ySchedulers.computation()
(delimitados por el número de núcleos) y no gira uno nuevo cada vez como lo hace su código sugerido. Lo que obviamente también puedes hacer manualmente:Esto debería ser mejor que crear un hilo para cada tarea, generalmente hablando, permitiendo reutilizar hilos existentes, pero depende de su uso.
Si las corutinas son útiles para esto depende mucho de lo que tenga dentro de sus tareas. ¿Una API de bloqueo (por ejemplo, JDBC)? No lo son ¿Una asíncrona (por ejemplo, Retrofit)? Son.
fuente
Los servicios Java Executor usan Threads y RxKotlin usa ExecutorServices. Entonces, todos estos son iguales en el fondo. La diferencia es la arquitectura de software. Entonces, si elige que la mejor arquitectura se integre con su código, funcionará mejor y hará el trabajo correctamente. Simple es lo mejor.
Si tiene una arquitectura basada en eventos u observable y está tratando de implementar una nueva biblioteca para trabajar con operaciones o trabajos basados en eventos, podría escribir pasos incorrectos sobre la separación o el tiempo del trabajo. Usa RxKotlin y no vuelvas a inventar la rueda.
Si su trabajo no se trata de eventos o patrones observables y solo necesita hacer trabajos paralelos, simplemente use los servicios de Ejecutor. El RxKotlin habrá terminado la ingeniería. Cuando usa RxKotlin en esta situación, necesita hacer más cosas de las que necesita.
Así que creo que la pregunta no es la velocidad en esta situación, sino la arquitectura.
fuente