RX vs Theads vs Executorsのマルチヘッドのパフォーマンス


8

Kotlinでバックエンドアプリケーションを作成しています。

速度を上げるために、私は現在、サーバーのRxKotlinを使用して、データベース呼び出しやAPI呼び出しなどのIOタスクの並列実行を行っています。コードは通常、次のようになります。

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()

ただし、実際には複数のイベント(単一のイベント)では機能しないため、Rxは少し乱雑な感じになり、ボイラープレートの束を追加するだけです(null値を返したい場合や、スタックトレースをめちゃくちゃにする可能性がある場合にも複雑になります) )

Executors代わりに、Rxを削除して並列処理に使用(またはスレッド)することを考えています。ここで考慮すべきパフォーマンスの考慮事項はありますか?

私が考えている例:

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
}

そしてそれを次のように使用します:

waitAll(listOf(callable1, callable2))

または、通常のスレッドを使用してそれらに参加しますか?

threads.forEach{
   it.start()
}
threads.forEach{
   it.join()
}

または、なぜストリーミングしないのですか?

listOf(callable1,callable2)
.parallelStream()
.map{it.call()}
.collect(Collectors.toList())

1
何を意味するのですか? Rxは少し乱雑に感じ、定型文の束を追加するだけです(null値を返したい場合にスタックトレースをめちゃくちゃにする可能性がある場合も複雑になります)
バブル

1
神の愛のために、スレッドルートに行くな。適切なタスクの抽象化が必要であり、スレッドが非常にすばやく乱雑になります。制限に達しない場合、ストリームルートはより有望に見えます。何かがより複雑になった場合は、おそらくRxKotlinをコルーチンに置き換えます。RxKotlinと同じスコープを持ち、どこかで記述したUIに限定されませんが、より慣用的に感じられます。
Arvid Heise、

回答:


4

KotlinRx自体はエグゼキューターを使用しますが、Schedulers.io()(無制限)とSchedulers.computation()(コアの数によって制限される)の下に2つの事前に作成されたスレッドプールがあり、提案されたコードのように毎回新しいプールを起動しません。明らかにあなたも手動で行うことができます:

private val executor = Executors.newCachedThreadPool() // equivalent to io()

fun <T> waitAll(tasks: List<Callable<T>>): List<T> {
    return executor.invokeAll(tasks).map {
        it.get()
    }
}

これ、一般的に言えば、既存のスレッドを再利用できるようにすることで、タスクごとにスレッドを作成するよりも優れていますが、使用方法によって異なります。

コルーチンは(IMO)バックグラウンド/ UIスレッド通信(つまり、Androidなど)の処理により適しています

コルーチンがこれに非常に役立つかどうかは、タスク内に何があるかによって異なります。ブロッキングAPI(JDBCなど)?そうではありません。非同期のもの(例:Retrofit)?彼らです。


5

Java Executorサービスはスレッドを使用し、RxKotlinはExecutorServicesを使用します。したがって、これらはすべてバックグラウンドで同じです。違いはソフトウェアアーキテクチャです。したがって、コードに統合する最適なアーキテクチャを選択すると、それが最もよく機能し、正しく機能します。シンプルが最高です。

イベントベースまたは監視可能ベースのアーキテクチャがあり、イベントベースの操作またはジョブを処理する新しいライブラリを実装しようとしている場合、ジョブの分離またはタイミングについて誤った手順を記述する可能性があります。RxKotlinを使用して、ホイールを再発明しないでください。

イベントや監視可能なパターンではなく、並列ジョブを実行する必要がある場合は、Executorサービスを使用するだけです。RxKotlinはエンジニアリングを超えます。この状況でRxKotlinを使用する場合は、必要なことより多くのことを行う必要があります。

だから問題はこの状況でのスピードではなく、アーキテクチャだと思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.