본문으로 건너뛰기

[Ray] 압력 기반 메모리 모니터 도입으로 메모리 관리 고도화

PR #61361 - [Core] (Resource Isolation 9/n) Add pressure based memory monitor

들어가며

Ray의 기존 메모리 모니터는 호스트의 meminfo를 주기적으로 폴링하여 설정된 임계값을 초과하면 워커를 종료하는 방식입니다. 하지만 메모리 관리의 진정한 목적은 특정 메모리 양의 사용을 제한하는 것이 아니라, 메모리 부족으로 인한 시스템 성능 저하를 방지하는 것입니다. 이 PR은 Linux cgroup의 PSI(Pressure Stall Information)를 활용한 압력 기반 메모리 모니터를 도입합니다.

핵심 코드 분석

PSI 트리거 등록

StatusSetOr<std::unique_ptr<PressureMemoryMonitor>,
            StatusT::InvalidArgument, StatusT::IOError>
PressureMemoryMonitor::Create(MemoryPsi pressure_threshold,
                              std::string cgroup_path,
                              KillWorkersCallback kill_workers_callback) {
    // memory.pressure 파일 오픈
    std::string memory_pressure_path =
        cgroup_path + "/memory.pressure";
    int pressure_fd = open(memory_pressure_path.c_str(), O_RDWR | O_NONBLOCK);

    // PSI 트리거 문자열: "<mode> <threshold_us> <window_us>"
    uint32_t window_us = pressure_threshold.stall_duration_s * 1000000;
    uint32_t threshold_us =
        static_cast<uint32_t>(pressure_threshold.stall_proportion * window_us);
    std::string trigger_str =
        absl::StrFormat("%s %u %u", pressure_threshold.mode, threshold_us, window_us);

    // PSI 트리거 등록
    write(pressure_fd, trigger_str.c_str(), trigger_str.length());
}

모니터링 스레드 (poll 기반)

void PressureMemoryMonitor::MonitoringThreadMain() {
    struct pollfd fds[2];
    fds[0].fd = pressure_fd_;     // PSI 이벤트
    fds[1].fd = shutdown_event_fd_; // 종료 신호

    while (true) {
        int ret = poll(fds, 2, -1); // PSI 이벤트 대기
        if (fds[1].revents & POLLIN) break; // 종료
        if (fds[0].revents & POLLPRI) {
            // 메모리 압력 감지 -> 워커 종료
            kill_workers_callback_();
        }
    }
}

안전한 종료

PressureMemoryMonitor::~PressureMemoryMonitor() {
    uint64_t val = 1;
    write(shutdown_event_fd_, &val, sizeof(val)); // eventfd로 종료 신호
    pressure_monitoring_thread_.join();
    close(shutdown_event_fd_);
    close(pressure_fd_);
}

왜 이게 좋은가

  1. 반응적 메모리 관리: 정적 임계값이 아닌, 실제 메모리 압력(프로세스가 메모리 대기로 stall된 비율)에 반응합니다.
  2. poll 기반 이벤트 드리븐: 주기적 폴링 대신 커널이 PSI 트리거 조건 충족 시 알림을 보내므로 CPU 오버헤드가 최소화됩니다.
  3. 깔끔한 수명 주기: eventfd를 사용하여 모니터링 스레드를 안전하게 종료하고, 모든 파일 디스크립터를 정리합니다.
  4. 점진적 도입: 현재는 no-op으로 추가되어 있으며, 전체 메모리 모니터링 시스템이 완성될 때 통합될 예정입니다.

참고 자료

댓글

관련 포스트

PR Analysis 의 다른글