우리 시스템의 로드 평균에 이상한 상황이 있습니다. 하루 종일 유휴 상태인 ZAG라는 애플리케이션을 실행하고 있습니다. 하지만 매 80분마다 5~15분 동안 지속되는 일종의 폭발적인 활동이 있습니다. 버스트 시 부하 평균은 60, 70, 80, 100 이상으로 올라갈 수 있습니다. 흥미로운 사실: 이러한 높은 버스트 동안 우리는 htop의 CPU 사용률이 CPU당 10-20%만 표시되는 것을 볼 수 있습니다. 또한 내가 작성한 스크립트는 유휴 시간 동안 CPU 사용량이 낮다는 것을 보여줍니다.
ps -eTo psr,user,pid,tid,cputime,class,rtprio,ni,pri,pcpu,stat,wchan:14,args | grep ZAG | awk '{sum += $10} END{print sum;}'
535.0을 반환할 수 있습니다. 즉, ZAG 응용 프로그램의 모든 CPU 백분율을 추가하면 CPU의 535.0%, 즉 시스템의 모든 CPU 사용률이 5.35/32 또는 16.7%가 반환됩니다. 간단히 말해서, CPU 중 어느 것도 100%에 가깝게 실행되지 않았는데, 이는 대부분의 유휴 시간 동안 우리가 예상했던 것입니다.
이 경우 결과는 약 538.0%... 조금 더 높을 뿐입니다. 또한 아래와 같이 실행 대기열에 더 많은 스레드가 표시됩니다.
while true; do ps -eTo psr,user,pid,tid,cputime,class,rtprio,ni,pri,pcpu,stat,wchan:14,args | grep ZAG | grep ' Rl' | wc -l; sleep 0.5; done
결과적으로 CPU 사용률이 약간 올라가고 더 많은 스레드가 실행됩니다. 하지만 부하 평균이 치솟아도 CPU 사용량은 늘어나지 않는 것 같습니다. 디스크 I/O 또는 네트워크 I/O와 관련하여 항상 거의 발생하지 않았습니다. 이번 사태 동안 SAR 데이터는 크게 증가하지 않았습니다. 메모리 활용도는 증가하지 않으며, 시스템의 전체 프로세스 약 1700개 중 프로세스 수도 약간 증가할 수 있지만 그게 전부입니다. 이 시간 동안 cron에서는 아무 일도 일어나지 않습니다. htop 또는 top 출력은 현재 일부 CPU 사용률(주로 사용자 CPU)이 실제로 발생하고 있음을 보여줍니다(top에서는 시스템 CPU가 5% 미만이라고 보고함). 따라서 데이터를 기다리는 것이 아무것도 없는 것 같습니다.
나는 /proc/interrupts에서 특이한 점을 발견하지 못했습니다. 일정 조정 중단이 심한 것 같으나 짝수 및 홀수 NUMA 노드를 포함해 6개의 코어를 확인해보니 프로세서당 초당 1400 정도에서 안정적인 것으로 보였습니다.
이는 하이퍼스레딩이 켜진 16코어 머신(E5-2667 v4 프로세서)입니다. 여기에는 각각 ps -ef 및 ps -eTf로 표시되는 36개의 ZAG 프로세스와 729개의 ZAG Therad가 있습니다.
그래서 궁금해졌습니다. 내 CPU 사용률은 왜 그렇게 낮고 로드 평균은 그렇게 높은 걸까요? 36개의 ZAG 프로세스 중 700개가 넘는 스레드가 있고 그 중 하나가 sched_yield()
여전히 실행 대기열에 있지만 CPU를 축적하지 않기 때문일까요? 아니면 sched_yield()
더 이상 실행할 수 없지만 중단할 수 없는 상태에 있습니까(아래 참조)?
브렌든 그레그에 따르면https://www.brendangregg.com/blog/2017-08-08/linux-load-averages.html, "부하 평균이 Linux에서 처음 나타났을 때는 다른 운영 체제와 마찬가지로 CPU 수요를 반영했습니다. 그러나 나중에 Linux에서는 실행 가능한 작업뿐만 아니라 중단할 수 없는 상태(TASK_UNINTERRUPTIBLE 또는 nr_uninterruptible)의 작업도 포함하도록 변경했습니다. 이 상태는 다음에서 사용됩니다. 차단된 작업 및 디스크 I/O의 일부 잠금을 포함하여 신호 중단을 피하려는 코드 경로... 그러나 Linux 로드 평균은 설명할 수 있는 정도까지 디스크 I/O보다 높지 않은 경우가 있습니다. 1993년에는 존재하지 않았던 TASK_UNINTERRUPTIBLE을 사용하는 새로운 코드 경로 때문인 것으로 추측됩니다. Linux 0.99.14에는 TASK_UNINTERRUPTIBLE 또는 TASK_SWAPPING(나중에 스왑 상태가 제거됨)을 직접 설정하는 13개의 코드 경로가 있습니다. Linux 4.12에는 일부 잠금 프리미티브를 포함하여 TASK_UNINTERRUPTIBLE을 설정하는 거의 400개의 코드 경로가 있으며 이러한 코드 경로 중 하나는 로드 평균에 포함되어서는 안 됩니다..."
답변1
찾은 것 같아요.
질문은 간단합니다.
높은 로드 평균(즉, 실행 대기열에 많은 항목)과 낮은 CPU 사용률을 설명하는 방법은 무엇입니까?
나는 그 답이 sched_yield() 시스템 호출에 있다고 믿습니다. 스레드가 다른 스레드에 양보하는 경우 해당 스레드는 CPU의 실행 대기열에 남아 있지만 많은 작업을 수행하지 못할 수 있습니다.
링크가 사라지는 경우: Bovet 및 Cesati의 2판 "Linux 커널 이해" 370페이지입니다.
"sched_yield() 시스템 호출을 사용하면 프로세스가 일시 중단되지 않고 자발적으로 CPU를 포기할 수 있습니다. 프로세스는 task_running 상태로 유지되지만 스케줄러는 이를 실행 대기열 목록의 끝에 배치합니다. 이렇게 하면 다른 프로세스가 동일한 동적 우선순위를 가진 프로세스는 실행될 기회가 있습니다. 이 호출은 주로 sched_fifo 프로세스에서 사용됩니다."
여기서 그들은 "프로세스"를 언급하지만 맨 페이지에는 있습니다.https://man7.org/linux/man-pages/man2/sched_yield.2.html설명에는 "sched_yield()로 인해 호출 스레드가 CPU를 포기하게 됩니다. 스레드는 정적 우선순위로 인해 대기열의 끝으로 이동되고 새 스레드가 실행되기 시작합니다."라고 나와 있습니다.
따라서 개념적으로 우리는 동일한 동작을 가집니다. 즉, 실행 대기열 목록의 끝에 도달합니다. 우리가 본 내용에 따르면 스레드가 task_running 상태를 유지하는 것이 합리적입니다.