상세 컨텐츠

본문 제목

[RxSwift] Scheduler.2

iOS/RxSwift

by kimrindev 2024. 12. 16. 21:10

본문

Serial vs Concurrent Schedulers

“직렬(Serial) 스케줄러와 병렬(Concurrent) 스케줄러”

 

Since schedulers can really be anything, and all operators that transform sequences need to preserve additional implicit guarantees, it is important what kind of schedulers are you creating.

 

스케줄러는 사실 어떤 형태로든 될 수 있으며, 시퀀스를 변환하는 모든 연산자는 추가적인 암시적 보장을 유지해야 하므로, 어떤 종류의 스케줄러를 생성하는지가 중요합니다.

scheduler 는 Rx에서  작업이 어디서 실행될지 결정하는 도구, 
Swift에서 UI작업을 메인쓰레드에서 작동하고 데이터 다운로드/ 이미지처리을 백그라운드 쓰레드로 처리하듯이

 


직렬 스케쥴러(Serial Scheduler) / 병렬스케쥴러(Concurrent Scheduler) 가 존재하는것 

  •  직렬은 한마디로 MainThread처럼 순서대로 실행하는 작업 : UI작업은 한번에 하나씩 실행되야함
  •  병렬은 여러가지의 작업을 동시에 실행 :독립적인 작업은 병렬로 작업하는것이 효율적임

 

In case the scheduler is concurrent, Rx's observeOn and subscribeOn operators will make sure everything works perfectly.

 

스케줄러가 병렬적인 경우, Rx의 observeOn 및 subscribeOn 연산자가 모든 작업이 완벽히 동작하도록 보장합니다.

 

보장해야한다? 


Rx에서는 병렬작업을 처리할때 작업간 충돌이 발생하지 않도록 관리가 필요함 ( 두작업이 동시에 데이터를 수정하면 문제가 생길수 있음 )
그렇기때문에 Rx에서 observeOn / SubscribeOn을 통해서 작업의 실행환경을 제어함

 

subscribeOn으로 데이터 흐름의 시작점이 어떤스케쥴러에서 실행될지 설정 후
observeOn으로 데이터 흐름 중간 또는 끝에서 어떤 스케쥴러를 사용할지 설정. 

 

Observable.just("Fetching Data")
    .subscribeOn(Schedulers.io())  // 백그라운드 스레드에서 실행
    .observeOn(MainScheduler.instance)  // UI 스레드에서 결과 처리
    .subscribe { print($0) }

 

 

If you use some scheduler that Rx can prove is serial, it will be able to perform additional optimizations.

 

Rx가 직렬 스케줄러임을 증명할 수 있는 경우, 추가적인 최적화를 수행할 수 있습니다.

직렬스케쥴러는 한번에 하나의 작업만으로 처리하므로, 작업간의 충돌/ 꼬임 을 걱정할필요가 없음

 

 

So far it only performs those optimizations for dispatch queue schedulers.
In case of serial dispatch queue schedulers, `observeOn` is optimized to just a simple dispatch_async call.

 

현재까지 이러한 최적화는 디스패치 큐 스케줄러에서만 수행됩니다. 직렬 디스패치 큐 스케줄러의 경우, observeOn은 단순한 dispatch_async 호출로 최적화됩니다.

직렬 디스패치 큐 에서 observeOn이 호출되면 복잡한 동작없이 간단히 dispatch_async를 호출하는 방식으로 최적화됩니다.

 

 

 

(이 하단부분은 이해를 하기에 시간이 오래걸릴것으로 예상되어서 따로 학습해보고 정리하려고 한다)

Custom Schedulers

Besides current schedulers, you can write your own schedulers.

 

현재 Rx에서 제공하는 스케줄러 외에도, 사용자가 직접 스케줄러를 구현할 수 있습니다.

 

ImmediateScheduler

If you just want to describe who needs to perform work immediately, you can create your own scheduler by implementing the ImmediateScheduler protocol.

 

작업을 즉시 수행할 스케줄러를 정의하려면 ImmediateScheduler 프로토콜을 구현하여 커스텀 스케줄러를 만들 수 있습니다.

 

public protocol ImmediateScheduler {
    func schedule<StateType>(
        state: StateType,
        action: (StateType) -> RxResult<Disposable>
    ) -> RxResult<Disposable>
}

 

 

 

Scheduler

If you want to create a new scheduler that supports time-based operations, then you’ll need to implement the Scheduler protocol.

 

시간 기반 작업을 지원하는 새로운 스케줄러를 만들고 싶다면 Scheduler 프로토콜을 구현해야 합니다.

 

public protocol Scheduler: ImmediateScheduler {
    associatedtype TimeInterval
    associatedtype Time

    var now: Time { get }

    func scheduleRelative<StateType>(
        state: StateType,
        dueTime: TimeInterval,
        action: (StateType) -> RxResult<Disposable>
    ) -> RxResult<Disposable>
}

 

 

 

PeriodicScheduler

In case the scheduler only has periodic scheduling capabilities, you can inform Rx by implementing the PeriodicScheduler protocol.

 

스케줄러가 주기적인 작업을 지원한다면 PeriodicScheduler 프로토콜을 구현하여 Rx에 이를 알릴 수 있습니다.

 

public protocol PeriodicScheduler: Scheduler {
    func schedulePeriodic<StateType>(
        state: StateType,
        startAfter: TimeInterval,
        period: TimeInterval,
        action: (StateType) -> StateType
    ) -> RxResult<Disposable>
}

 

In case the scheduler doesn’t support PeriodicScheduling capabilities, Rx will emulate periodic scheduling transparently.

 

스케줄러가 주기적인 작업을 지원하지 않는 경우, Rx는 이를 투명하게 에뮬레이션합니다.

 

CurrentThreadScheduler (Serial Scheduler)

 

 

Schedules units of work on the current thread. This is the default scheduler for operators that generate elements.

This scheduler is also sometimes called a “trampoline scheduler”.

If CurrentThreadScheduler.instance.schedule(state) { }is called for the first time on some thread, the scheduled action will be executed immediately and a hidden queue will be created where all recursively scheduled actions will be temporarily enqueued.

If some parent frame on the call stack is already running

CurrentThreadScheduler.instance.schedule(state) { }__, the scheduled action will be enqueued and executed when the currently running action and all previously enqueued actions have finished executing.

 

 

  •  CurrentThreadScheduler는 현재 스레드에서 작업을 실행하는 스케줄러입니다.
  •  연산자가 요소를 생성할 때 기본적으로 사용하는 스케줄러입니다.
  • “Trampoline Scheduler”라고도 불리며, 이는 작업을 재귀적으로 실행할 때 내부적으로 숨겨진 큐를 사용하기 때문입니다.
  •  특정 스레드에서 CurrentThreadScheduler.instance.schedule이 처음 호출되면 작업이 즉시 실행되고, 재귀적으로 스케줄링된 작업을 임시로 저장하는 숨겨진 큐가 생성됩니다.
  •  만약 이미 CurrentThreadScheduler가 실행 중인 경우, 새 작업은 큐에 추가되고 현재 실행 중인 작업과 이전에 추가된 모든 작업이 완료된 후에 실행됩니다.

 

MainScheduler (Serial Scheduler)

Abstracts work that needs to be performed on MainThread.
In case schedule methods are called from main thread, it will perform the action immediately without scheduling.

This scheduler is usually used to perform UI work.

 

  •   MainScheduler는 작업을 메인 스레드(UI 스레드)에서 실행하도록 추상화한 스케줄러입니다.
  •  만약 메인 스레드에서 schedule 메서드가 호출되면, 큐에 추가하지 않고 작업을 즉시 실행합니다. 
  •  이 스케줄러는 주로 UI 관련 작업을 수행할 때 사용됩니다.

SerialDispatchQueueScheduler (Serial Scheduler)

 

Abstracts the work that needs to be performed on a specific dispatch queue t.
It will make sure that even if a concurrent dispatch queue is passed, it’s transformed into a serial one.

Serial schedulers enable certain optimizations for observeOn.
The main scheduler is an instance of SerialDispatchQueueScheduler.

 

  •  SerialDispatchQueueScheduler는 특정 디스패치 큐(dispatch queue t)에서 작업을 실행하도록 추상화한 스케줄러입니다.
  •  병렬 디스패치 큐를 전달하더라도, 내부적으로 이를 직렬 큐(serial queue)로 변환하여 실행합니다.
  •  Serial 스케줄러는 observeOn 연산자에서 특정 최적화를 가능하게 합니다.
  •  MainScheduler는 SerialDispatchQueueScheduler의 한 인스턴스입니다.

 

 

ConcurrentDispatchQueueScheduler (Concurrent Scheduler)

Abstracts the work that needs to be performed on a specific dispatch queue t.

You can also pass a serial dispatch queue; it shouldn’t cause any problems.

This scheduler is suitable when some work needs to be performed in the background.

 

  • ConcurrentDispatchQueueScheduler는 특정 **디스패치 큐(dispatch_queue_t)**에서 작업을 실행하도록 추상화한 스케줄러입니다.
  •  직렬 디스패치 큐를 전달해도 문제가 발생하지 않습니다.
  •  이 스케줄러는 백그라운드에서 작업을 수행해야 할 때 적합합니다.

 

OperationQueueScheduler (Concurrent Scheduler)

 

Abstracts the work that needs to be performed on a specific NSOperationQueue.
This scheduler is suitable for cases when there is some bigger chunk of work that needs to be performed in the background and you want to fine tune concurrent processing using maxConcurrentOperationCount.

 

  •  OperationQueueScheduler는 특정 NSOperationQueue에서 작업을 실행하도록 추상화한 스케줄러입니다.
  •  이 스케줄러는 대규모 작업을 백그라운드에서 처리해야 하며, maxConcurrentOperationCount를 사용하여 동시 실행 가능한 작업 수를 세밀하게 조정해야 하는 경우에 적합합니다.

 

 

 

 

 

 

 

 

 

 

 

 

'iOS > RxSwift' 카테고리의 다른 글

[RxSwift] Implicit Observable Guarantees  (3) 2024.12.21
[RxSwift] Disposing  (2) 2024.12.18
[RxSwift] Scheduler.1  (2) 2024.12.12
[RxSwift] DesignRationale  (3) 2024.12.08
[RxSwift] Basic.2  (3) 2024.11.29

관련글 더보기