sysinfo: a performance journey
sysinfo, 스레드 GPU 정보 재수집을 줄여 Linux 갱신 시간 단축
sysinfo 개발자가 Linux에서 GPU 사용량을 수집하며 생긴 성능 부담을 줄인 과정을 공개했습니다. 파일 디스크립터 테이블을 부모와 공유하는 스레드는 GPU 정보를 다시 읽지 않고 부모 값을 복사해, 제시한 한 실행에서 갱신 시간이 0.312초에서 0.110초로 줄었습니다. getdents64의 버퍼 크기 설명과 별도 벤치마크 수치는 이 결과와 구별됩니다.
- 주제
본문
Rust 시스템 정보 라이브러리 sysinfo 개발자는 Linux에서 프로세스별 GPU 사용량을 수집하면서 커진 성능 부담을 두 달간 줄인 과정을 공개했습니다. 가장 큰 개선은 파일 경로나 파싱을 미세 조정한 데서 나오지 않았습니다. 부모 프로세스와 파일 디스크립터 테이블을 공유하는 스레드는 GPU 정보를 다시 읽지 않고 부모의 값을 복사하도록 바꿨습니다.
sysinfo는 프로세스와 메모리 같은 시스템 정보를 프로그램에서 조회하는 라이브러리입니다. 0.40.0에는 GPU 사용량·메모리 API가 추가됐고 Linux 성능 최적화도 포함됐습니다. GPU 정보를 모으려면 각 프로세스의 파일 디스크립터 정보를 살펴 GPU 장치와 관련된 항목을 찾아야 합니다. 개발자는 처음에 모든 항목을 읽는 대신 경로가 /dev/dri/ 또는 /dev/accel/로 시작하는 항목만 추렸습니다. 글에 실린 실행 결과에서 전체 항목을 살핀 바이너리는 2.414초, 필터링한 바이너리는 0.443초, GPU 기능을 넣기 전 바이너리는 0.108초가 걸렸습니다. 프로세스 수도 각 실행에서 달라진 비교 결과입니다.
개발자는 이후 경로 문자열 비교를 줄이고 파일 접근 방식을 바꾸거나 프로세스 정보를 파싱하고 메모리를 재사용하는 등 여러 변경을 시도했습니다. 일부 변경은 명령어 수나 메모리 할당량을 줄였지만, 성능 향상 폭이 작거나 실행 시간에 차이가 없었습니다. 디렉터리 읽기 부분에서는 getdents64의 count를 한 번에 읽을 항목 수로 설명했지만, Linux 매뉴얼에서 이 값은 결과를 담을 버퍼의 크기입니다. 글에 제시된 해당 변경 전후 실행 시간도 0.103초에서 0.349초로 늘었습니다. 뒤이어 openat·readlinkat 등을 적용한 변경이 함께 설명돼 있어 이 측정만으로 각 변경의 효과를 따로 판단하기 어렵습니다.
큰 변화는 Linux의 스레드 구조에서 나왔습니다. 부모 프로세스와 파일 디스크립터 테이블을 공유하는 스레드는 같은 파일 디스크립터를 쓰므로 GPU 정보를 별도로 다시 수집할 필요가 없습니다. sysinfo는 테이블 공유 여부를 확인해 해당 스레드에 부모의 GPU 정보를 복사하도록 바꿨습니다. unshare로 테이블이 달라진 경우는 예외로 두고 kcmp의 KCMP_FILES로 공유 여부를 확인합니다. 개발자가 제시한 한 실행에서는 경과 시간이 0.312초에서 0.110초로 줄었고 명령어 수도 약 65% 감소했습니다. 병합된 변경 요청에는 별도 벤치마크의 중앙값이 0.421초에서 0.141초로 줄었다고 기록돼 있습니다. 두 수치는 측정 결과가 서로 다른 비교이므로 하나의 실행치로 합칠 수 없습니다.
마지막으로 sysinfo 0.40.0은 프로세스 정보를 갱신할 때 열 수 있는 파일 수를 설정하던 set_open_files_limit API를 제거했습니다. 개발자는 프로세스의 /proc/{PID}/stat 파일을 다시 여는 대신 계속 열어 두고 읽기 위치를 되돌리는 편이 빠르다는 이유를 들었습니다. 블로그의 전후 실행 시간은 0.312초와 0.302초로 차이가 작았습니다.
자료: Guillaume Gomez의 블로그, sysinfo GitHub 변경 내역 / 정리·해설: Trawling
참고 자료
- sysinfo/CHANGELOG.md at main · GuillaumeGomez/sysinfo · GitHub — https://github.com/GuillaumeGomez/sysinfo/blob/main/CHANGELOG.md
- Linux: Skip threads GPU refresh and copy their parent process value afterward by GuillaumeGomez · Pull Request #1768 · GuillaumeGomez/sysinfo — https://github.com/GuillaumeGomez/sysinfo/pull/1768
- getdents(2) - Linux manual page — https://man7.org/linux/man-pages/man2/getdents.2.html