Skip to content

Latest commit

ย 

History

History
78 lines (62 loc) ยท 3.25 KB

File metadata and controls

78 lines (62 loc) ยท 3.25 KB

Fipe

Fipe๋Š” Kotlin Flow๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ์ ์ด๊ณ  ์กฐ๋ฆฝ ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•œ ๊ฒฝ๋Ÿ‰ Kotlin Multiplatform ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.
์ž‘๊ณ  ์ง‘์ค‘๋œ ์ฒ˜๋ฆฌ ๋‹จ๊ณ„๋ฅผ ์—ฐ๊ฒฐํ•˜์—ฌ(์˜ˆ: ๋งคํ•‘, ๋ฒ„ํผ๋ง, ๋ณ‘๋ ฌ ๋ณ€ํ™˜) ๋ณต์žกํ•˜๊ณ  ํšจ์œจ์ ์ธ ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŠน์ง•

  • ์กฐ๋ฆฝ ๊ฐ€๋Šฅํ•œ ํŒŒ์ดํ”„๋ผ์ธ: ์—ฌ๋Ÿฌ ๋ณ€ํ™˜ ๋‹จ๊ณ„๋ฅผ (then) ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • ์œ ์—ฐํ•œ ๋‹จ๊ณ„: ๋งคํ•‘, ๋ฒ„ํผ๋ง, ๊ณต์œ , ์ƒํƒœ ์ฒ˜๋ฆฌ, ๋ณ‘๋ ฌ ์ˆœ์„œ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ์„ ๊ธฐ๋ณธ ์ œ๊ณตํ•˜์—ฌ ๋‹ค์–‘ํ•œ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
  • Kotlin Multiplatform ์ง€์›: JVM, Android, iOS ๋“ฑ ๋‹ค์–‘ํ•œ ํ”Œ๋žซํผ์—์„œ ์‹คํ–‰ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  • Coroutine ๋ฐ Flow ๊ธฐ๋ฐ˜: Coroutine ๋ฐ Flow๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋น ๋ฅธ ์˜ˆ์ œ

 // ๊ฐ„๋‹จํ•œ ํŒŒ์ดํ”„๋ผ์ธ ์˜ˆ์ œ
 fun main() = runBlocking {
    val bufferSize = 30
    val doublingStep = MapStep<Int, Int> { delay(30); it * 2 }
    val toDoubleStep = MapStep<Int, Double> { delay(60); it.toDouble() }
    val incrementStep = MapStep<Double, Double> { it + 1 }

    fun getPipeline(useBuffer: Boolean): Fipe<Int, Double> = fipe<Int>()
        .then(doublingStep)
        .let { if (useBuffer) it.thenBuffer(bufferSize) else it }
        .then(toDoubleStep)
        .let { if (useBuffer) it.thenBuffer(bufferSize) else it }
        .then(incrementStep)

    suspend fun Fipe<Int, Double>.pipelineResult(): List<Double> {
        return Dispatchers.Default {
            toFlow(
                flow {
                    repeat(bufferSize) {
                        delay(30)
                        emit(it)
                    }
                }
            ).take(bufferSize).toList()
        }
    }

    val n = bufferSize
    val t1 = 30L
    val t2 = 60L
    val t3 = 0L

    val expectedSequential = ((t1 + t2 + t3) * n).milliseconds
    val expectedPipeline = (t1 + (n - 1) * maxOf(t1, t2, t3)).milliseconds

    val pipelineWithoutBuffer = getPipeline(false)
    val pipelineWithBuffer = getPipeline(true)

    val timeWithoutBuffer = measureTime { pipelineWithoutBuffer.pipelineResult() }
    val timeWithBuffer = measureTime { pipelineWithBuffer.pipelineResult() }

    println("์ด๋ก ์ƒ ์ตœ์†Œ ์‹œ๊ฐ„ (์ˆœ์ฐจ ์ฒ˜๋ฆฌ): $expectedSequential")
    println("์ด๋ก ์ƒ ์ตœ์†Œ ์‹œ๊ฐ„ (ํŒŒ์ดํ”„๋ผ์ธ ์ฒ˜๋ฆฌ): $expectedPipeline")
    println("์‹ค์ œ ์ˆœ์ฐจ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: $timeWithoutBuffer")
    println("์‹ค์ œ ํŒŒ์ดํ”„๋ผ์ธ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: $timeWithBuffer")
}

์ด๋ก ์ƒ ์ตœ์†Œ ์‹œ๊ฐ„ (์ˆœ์ฐจ ์ฒ˜๋ฆฌ): 2.7s

์ด๋ก ์ƒ ์ตœ์†Œ ์‹œ๊ฐ„ (ํŒŒ์ดํ”„๋ผ์ธ ์ฒ˜๋ฆฌ): 1.77s

์‹ค์ œ ์ˆœ์ฐจ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 3.958783583s

์‹ค์ œ ํŒŒ์ดํ”„๋ผ์ธ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 2.050898667s

ํŒŒ์ดํ”„๋ผ์ธ์€ .then(...)์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ๊ณ„๋ฅผ ์—ฐ๊ฒฐํ•˜๋ฉฐ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.
๊ฐ ๋‹จ๊ณ„๋Š” ํ๋ฆ„ ๋‚ด์—์„œ ์š”์†Œ๋ฅผ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜, ๋ฒ„ํผ๋งํ•˜๊ฑฐ๋‚˜, ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌํ•˜๋Š” ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด์ฒ˜๋Ÿผ ์ž‘์€ ์ฒ˜๋ฆฌ ๋‹จ๊ณ„๋ฅผ ๋ณ€์ˆ˜ํ™”ํ•˜๊ณ  ์กฐ๋ฆฝํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋กœ์ง์„ ํšจ์œจ์ ์ด๊ณ  ์œ ์—ฐํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ผ์ด์„ ์Šค

์ด ํ”„๋กœ์ ํŠธ๋Š” Apache License 2.0 ํ•˜์— ๋ผ์ด์„ ์Šค๊ฐ€ ๋ถ€์—ฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.