Estou escrevendo um aplicativo de back-end no Kotlin.
Para acelerar, atualmente estou confiando no RxKotlin no servidor para executar paralelamente tarefas de E / S, como chamadas de banco de dados e API. O código geralmente se parece com isso.
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()
No entanto, como o trabalho não funciona realmente com vários eventos (apenas singles), o Rx se sente um pouco confuso e apenas adiciona um monte de clichê (também causa complicações se eu quiser retornar um valor nulo e, às vezes, atrapalhar o rastreamento da pilha )
Estou pensando em remover Rx e usar Executors
(ou threads) para paralelismo insteada. Existem considerações de desempenho a serem consideradas aqui?
Exemplo no que estou 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
}
E usando-o assim:
waitAll(listOf(callable1, callable2))
Ou talvez usando threads regulares e se juntar a eles?
threads.forEach{
it.start()
}
threads.forEach{
it.join()
}
Ou por que não fluxos?
listOf(callable1,callable2)
.parallelStream()
.map{it.call()}
.collect(Collectors.toList())
fonte
Respostas:
O próprio KotlinRx usa executores, exceto que ele possui dois conjuntos de threads pré-criados em
Schedulers.io()
(ilimitado) eSchedulers.computation()
(limitado pelo número de núcleos) e não cria um novo a cada vez, como o código sugerido. O que você obviamente também pode fazer manualmente:Isso deve ser melhor do que criar um encadeamento para cada tarefa, geralmente falando, permitindo reutilizar encadeamentos existentes, mas depende do seu uso.
Se as corotinas são úteis para isso depende muito do que você tem em suas tarefas. Uma API de bloqueio (por exemplo, JDBC)? Eles não são. Um assíncrono (por exemplo, Retrofit)? Eles são.
fonte
Os serviços Java Executor usam Threads e RxKotlin usa ExecutorServices. Então, todos esses são os mesmos em segundo plano. A diferença é arquitetura de software. Portanto, se você escolher a melhor arquitetura para ser integrada ao seu código, ele funcionará melhor e fará o trabalho corretamente. O simples é o melhor.
Se você tiver uma arquitetura baseada em evento ou observável e estiver tentando implementar uma nova biblioteca para trabalhar com operações ou trabalhos com base em eventos, poderá escrever etapas erradas sobre separação ou tempo de trabalho. Use RxKotlin e não invente a roda novamente.
Se o seu trabalho não for sobre eventos ou padrão observável e você apenas precisar executar tarefas paralelas, use os serviços do Executor. O RxKotlin será sobre engenharia. Quando você usa o RxKotlin nessa situação, precisa fazer mais coisas do que precisa.
Então eu acho que a questão não é a velocidade nessa situação, a arquitetura é.
fonte