반응형
기존 문자를 전송하는 로직은 chunked(10)를 통해 10개의 배치를 만들고 배치 내부는 비동기로 실행하되, 배치 내부의 작업이 모두 끝나면 다음 배치로 넘어가는 순차 방식으로 구현을 했다.
// sendMmsFlowList: MutableList<Flow<MmsResp>>
val result = sendMmsFlowList.chunked (10).flatMap { batch ->
batch.map { job ->
async { job.first() }
}.awaitAll()
}
개수를 제한하여 처리했을 때 시스템 자원이 과부하되는 것도 방지하고 서버와 통신하는 부분도 더 안전하다고 생각을 했다. 다만 Data 타입에 Flow를 담고 처리하는 부분이 전체 코드를 지저분하게 만들었고, 준비된 작업이 모두 끝나야만 다음 10개의 작업이 시작된다는 것도 조금 걸렸다.
그러던 중 semaphore에 대해 알게 되었는데, semaphore는 코루틴에서 제공하는 함수로 동시에 사용할 수 있는 코루틴의 개수를 보장하여 하나의 작업이 끝나면 다음 작업을 자동으로 채워서 제한한 개수를 유지시켜 준다.
// mmsList: List<MmsReq>
val semaphore = Semaphore(10)
val result = mmsList.map { mmsData ->
async {
semaphore.withPermit {
sendMms(mmsData)
}
}
}.awaitAll()
semaphore를 적용하면서 동시성이 보장하여 10개의 작업이 계속 수행된다는 점이 좋았고, 확실히 관심사 분리가 되어서인지 코드가 정돈됨을 느꼈다. (속도 차이는 20개 기준으로 큰 차이는 없었다)
단, semaphore는 withPermit이 실행되면서 코루틴이 일시 중단되었다가 재개되는데, 아이템의 개수가 많고 개별 작업 시간이 매우 짧다면 컨텍스트 스위칭으로 인한 오버헤드가 작업 시간보다 커지는 문제가 발생할 수 있다고 한다. (작업 개수만틈 Deferred 객체가 생성 됨)
두 함수를 비교하여 사용할 때 충분한 테스트가 필요할 것 같다.
chunked
- 작업시간에 편차가 없는 경우
- 리스트가 매우 큰 경우
- 코루틴 개수와 메모리를 확실히 제한하려는 경우
semaphore
- 작업시간에 편차가 있는 경우
- 리스트가 고정되지 않고 추가 및 삭제로 변경되는 경우 동시성을 제한할 때
- 전체 작업 시간을 단축하고 싶을 때
반응형
'작업 일지' 카테고리의 다른 글
| [Android] WebView에서 다운로드 동작이 안 되는 이유 (0) | 2025.09.17 |
|---|---|
| [Android] 배송 순서 최적화하기 with TSP (2) | 2025.07.01 |
| [Android][Compose] MaterialCalendarView를 Compose에서 사용하기 (0) | 2024.05.19 |
| [Android] 내비게이션의 다음 경로 정보 구하기#2 (0) | 2024.03.07 |
| [Android] 내비게이션의 다음 경로 정보 구하기#1 (5) | 2024.03.05 |