1. 주의할 점

  1. actor에서 await 호출 이후 내부 상태 가정 금지

    1. actor 내부에서 await 를 호출한 이후, actor 의 상태는 크게 변할 수 있습니다.
    actor MyDownloader {
        var counter = 0
        func download(url: URL) async throws -> Data {
            counter += 1 // counter 1 올리고
            let num = counter // counter 를 num 에 할당
            let result = try await URLSession.shared.data(from: url) // await 로 URLSession 함수 호출
    
            print("num : " + num.description + ", " + "counter : " + counter.description)
            print(num == counter) // counter 를 그대로 num 에 할당했으니까 true.. 일까나?
          
            return result.0
        }
    }
    

await 이후 counter의 상태를 예상할 수 없기 때문에, 모두 같은 값이 print될 것이라 예측할 수 없습니다. Task1에서 actor의 메소드를 실행하던 중, await을 만나면 suspend됩니다. 이때 다른 Task가 actor에 접근해 내부 프로퍼티를 변경할 수도 있기 때문에, 같은 값을 예상할 수 없는 것입니다.

  1. actor 에서 많은 양의 작업을 진행하지 않는다

    Untitled

    1. actor는 Task 의 접근을 직렬화(serialize) 합니다. actor의 접근이 가능해질 때까지 모든 Task가 대기하는 방식은 병렬 컴퓨팅의 이점을 잃게 됩니다.
    2. Actor에서 진행하는 작업이 길어질수록, 다른 Task가 Actor 접근을 위해 대기하는 시간도 길어지니까 각 Task는 빨리 끝나지 못하게 됩니다.
    3. 따라서 Task가 actor의 data에 접근이 필요한 경우에만 actor에서 실행되도록 해야 합니다.
    4. 작업을 잘게 쪼개 actor에서 실행될 것과 아닌 것을 나누고, actor에서 분리된 부분은 병렬로 진행시켜 컴퓨터가 전체 작업을 더 빨리 끝내도록 할 수 있습니다.

    작업을 쪼개 병렬화한 모습

    작업을 쪼개 병렬화한 모습

2. Actor Hopping

<aside> 💡 actor hopping actor의 동작은 cooperative thread pool에서 수행되는데, 한 actor에서 다른 actor로 전환되는 작업

</aside>

먼저, sports feed actor가 한 thread에서 실행되다, database actor의 save 함수를 호출합니다.

Untitled

이때 database actor는 사용되고 있지 않은, uncontended 상황입니다.

따라서 thread는 sports feed actor에서 database actor로 곧장 이동(hop)이 가능합니다.

Untitled

여기서 알 수 있는 사실은, actor를 전환(hop)하면서 이 thread는 block되지 않았고, hopping은 다른 thread를 필요로 하지 않았다는 점입니다.

이제 database actor의 D1이 실행되던 도중, weather feed actor가 database actor의 save함수를 호출합니다. 이것을 처리하기 위해 database actor에 대한 새로운 work item D2를 생성합니다.

Untitled

하지만 이때는 실행 중인 work item D1이 있기 때문에, D2는 보류 상태가 됩니다. 따라서 weather feed actor 또한 suspend 되어 해당 thread는 다른 일인 health feed를 수행합니다. 이후 D1작업이 완료되면, runtime이 보류중인 D2를 실행할지, 다른 feed actor를 실행할지, 아니면 아예 다른 작업을 실행할지 결정할 수 있습니다.

Untitled

이때 우선순위가 높은 작업을 먼저 수행하는 것이 중요한데, actor reentrancy의 개념으로 인해 시스템이 일의 우선 순위를 잘 반영할 수 있도록 설계되어 있습니다.