4P by neo 2달전 | favorite | 댓글 1개
  • Rust 커뮤니티에서 스레드는 async/await 가 할수 있는걸 다 할 수 있고 더 간단한데 왜 async/await를 선택하는가?라는 질문이 자주 보임
  • Rust는 저수준 언어로, Coroutine의 복잡성을 숨기지 않음. 이는 프로그래머가 비동기를 고려할 필요도 없이 기본적으로 비동기로 되는하는 Go와 같은 언어와 반대되는 개념
  • 똑똑한 프로그래머는 복잡성을 피하려고 노력하는데, async/await는 왜 필요한가?

배경 알아보기

  • Rust는 저수준 언어임. 코드는 일반적으로 선형적이며, 한 작업이 끝나면 다른 작업이 실행됨.
  • 웹 서버와 같은 동시에 많은 작업을 실행해야 하는 경우, 선형 코드로는 문제가 발생함.
  • 초기 웹은 스레딩을 도입하여 이 문제를 해결하려고 시도함.
  • 스레드를 사용하여 동시에 여러 클라이언트를 처리할 수 있으나, 프로그래머들은 OS 공간에서 사용자 공간으로 동시성을 가져오고자 함.

타임아웃 문제

  • Rust의 가장 큰 장점 중 하나는 조합성(composability) 임.
  • async/await는 I/O 바운드 함수에 이 조합성을 적용할 수 있게 함.
  • 예를 들어, 클라이언트 처리 함수에 타임아웃을 추가하고자 할 때, 두 개의 조합자를 사용하여 구현할 수 있음.

테마틱 스레드

  • 스레드를 사용한 예제에서 타임아웃을 구현하는 것은 쉽지 않음.
  • TcpStream에는 set_read_timeoutset_write_timeout 함수가 있지만, 이를 사용하는 것은 제한적임.
  • Rust의 조합자를 사용하여 타임아웃을 프로그래밍하는 방법을 제시하지만, 이는 TcpStream에만 국한되고 추가 시스템 호출이 필요함.

Async 성공 사례

  • HTTP 생태계는 async/await를 주요 런타임 메커니즘으로 채택함.
  • towerasync/await의 강력함을 보여주는 예로, 타임아웃, 속도 제한, 부하 분산 등을 제공함.
  • macroquad는 Rust 게임 엔진으로, async/await를 사용하여 엔진을 실행함.

Async의 이미지 개선

  • async의 이점이 널리 알려지지 않아 일부 사람들이 오해할 수 있음.
  • Rust 커뮤니티는 async Rust의 성능 이점을 과대평가하고 의미 있는 이점을 축소하는 경향이 있음.
  • async/await는 동기 Rust에서 수십 개의 스레드와 채널 없이는 표현할 수 없는 패턴을 간결하게 표현할 수 있는 강력한 프로그래밍 모델로 봐야 함.

GN⁺의 의견

  • async/await는 동시성을 처리할 때 코드의 복잡성을 증가시키지만, 동시에 많은 클라이언트를 효율적으로 처리할 수 있는 능력을 제공함.
  • 이 기사는 async/await가 단순히 성능상의 이점을 넘어서 프로그래밍 모델의 강점을 가지고 있음을 강조함.
  • Rust의 async/await는 다양한 I/O 작업에 대한 조합성을 제공하며, 이는 특히 네트워크 서비스나 웹 서버와 같은 분야에서 유용함.
  • 비판적인 시각에서 볼 때, async/await의 복잡성은 초보 개발자들에게 진입 장벽이 될 수 있으며, 이를 극복하기 위한 교육적 노력이 필요함.
  • 동일한 기능을 제공하는 다른 프로젝트로는 Node.js의 async/await 구현이나 Python의 asyncio 라이브러리가 있으며, 이들도 비슷한 패러다임을 제공함.
  • async/await를 도입할 때는 코드의 복잡성과 유지보수성을 고려해야 하며, 동시에 많은 클라이언트를 처리해야 하는 경우에는 이 모델이 큰 이점을 제공함.
Hacker News 의견
  • Async/await와 단일 스레드

    • 자바스크립트 모델처럼 단일 스레드에서의 async/await는 단순하고 잘 이해되어 있음.
    • 스레드를 사용하면 여러 CPU가 문제를 처리할 수 있고, Rust는 락 관리를 도와줌.
    • 다른 우선순위의 스레드를 가질 수 있으며, 계산에 제한이 있는 경우 필요함.
    • 멀티 스레드 async/await는 복잡함. 계산에 제한이 있는 섹션에서는 모델이 붕괴될 수 있음.
    • Rust에서 멀티 스레드 계산은 잘 작동하지 않음. 문제점으로는:
      • Futex 혼잡 붕괴: 일부 저장소 할당자에서 문제가 될 수 있음.
      • 불공정한 뮤텍스의 기아: 표준 Mutex와 crossbeam-channel 채널이 불공정함.
  • Async/await 대 스레드

    • 비판은 복잡성에 관한 것이 아니라, 선택에 따라 생태계가 분열되고 하나가 열등해지는 것에 대한 것임.
    • Rust 생태계는 IO 작업을 하려면 전부 async/await를 사용해야 한다고 결정함.
    • Rust가 async/await 이외의 것들을 더 조합 가능한 추상화로 만들었다면 불만이 사라졌을 것임.
  • 기사에 대한 문제점

    • 웹 서버 예시 하나만 제시되었고, 스레드에 대해 잘못 해결됨.
    • 프로그래머들은 OS 스레드가 아닌 개념적, 의미적 스레드를 원함.
    • OS 스레드는 비용이 많이 들고, 우리는 저렴한 스레드를 원함.
    • 웹 서버 예시에서의 타임아웃 구현 문제점.
  • 다루지 않은 순간들

    • async/await는 단일 스레드에서 실행되므로 락이나 동기화가 필요 없음.
    • async/await에서의 오류 전파는 명확하지 않음.
    • 네트워크 I/O에서 백프레셔도 언급되어야 함.
  • 취소에 관한 중요한 점

    • 미래의 어떤 작업도 쉽게 취소할 수 있음.
    • 스레드에서의 취소는 복잡하고, 강제 스레드 중단은 신뢰할 수 없음.
    • Rust의 async 모델에서는 모든 futures에 외부에서 타임아웃을 추가할 수 있음.
  • Async/await에 대한 마케팅 같은 캠페인

    • async/await는 기술적 실수였으며, 커뮤니티에 큰 비용을 초래함.
    • Rust는 여전히 가장 좋은 언어이지만, 이 논쟁이 영원히 이어질까 걱정됨.
  • Async/await 대 파이버

    • Rust는 이전에 그린 스레드를 가졌었고 의도적으로 제거됨.
    • futures를 언제든지 드롭할 수 있는 능력이 큰 비용을 수반함.
    • async/await의 조합성을 칭찬하는 것은 이상함.
  • Rust의 async/await 주요 이점

    • 스레드나 동적 메모리가 없는 상황에서도 작동할 수 있음.
    • 동시성을 사용하여 코드를 간결하게 작성할 수 있음.
  • Async/await에 대한 오해

    • 단일 스레드에서의 동시성 메커니즘이 필요한 이유를 이해하지 못하는 사람들이 있음.
    • UI 프로그래밍, GPU와의 통신, 런타임 간 통신 등에 async/await가 유용함.
  • Async/await 대 스레드 선택 이유

    • async/await는 클라이언트/요청/작업 상태의 메모리 사용량을 줄일 수 있음.
    • 상태 압축은 메모리 속도가 느린 현대에서 성능에 중요함.
    • async/await와 CPS는 클라이언트당 메모리 사용량을 줄이는 데 효과적임.