CPU 사용량이 1%인 프로세스로 인해 평균 로드가 1.5가 됩니다.

CPU 사용량이 1%인 프로세스로 인해 평균 로드가 1.5가 됩니다.

에 따르면 거의 모든 프로세스가 절전 모드에 있는 것으로 추정되지만 최근 임베디드 시스템에서 약 1.5의 높은 로드 평균을 관찰했습니다 htop.

문제의 시스템은 buildroot를 사용하여 구축된 실시간 Linux 커널(4.14.126)을 실행하는 듀얼 코어 Cortex-A9입니다. 우리는 루트 파일 시스템에 initramfs를 사용하고 있으며 스왑이 없습니다.디스크 I/O 없음정상 작동 중.

조금 조사한 결과 로드가 다음과 같은 프로그램에 의해 발생한다는 것을 알게 되었습니다.업데이트, 소프트웨어 업데이트를 위한 편리한 웹 인터페이스를 제공합니다(그리고 우리는 이를 계속 사용하고 싶습니다).

time해당 응용 프로그램의 평균 CPU 사용량을 추정하는 데 사용할 때 (계산하여)(사용자+sys)/실제), 약 1%의 값만 얻었는데, 이는 로드 평균 1.5를 고려하면 별 의미가 없습니다.

로드 평균에는 TASK_UNINTERRUPTIBLECPU 사용량에 영향을 주지 않는 상태의 프로세스도 포함된다는 것을 알고 있습니다. 내가 이해하지 못하는 것은 해당 응용 프로그램의 스레드/프로세스가 왜 그 상태에 있는지입니다.

상황을 더 자세히 분석하기 위해 다음을 사용하여 커널 추적을 캡처했습니다.ltngswupdate가 수행하는 유일한 작업은 다음과 같습니다(50ms마다). 여기에 이미지 설명을 입력하세요

그리고 이것은 (100ms마다): 여기에 이미지 설명을 입력하세요

보시다시피 소켓 기반 IPC로 보이는 것이 약간 있고 선택을 기다리고 있습니다.무엇. IPC의 경우 한 스레드는 대부분 에서 차단되고 nanosleep()다른 스레드는 에서 차단되는 것으로 보이며 accept(), 내가 아는 한 어느 쪽도 시스템 리소스를 소비해서는 안 됩니다.

참고: 두 스크린샷의 시간 기반은 동일하며 IPC에는 약 1시간이 소요됩니다. 총 500-600μs(50ms 간격을 고려하면 관찰된 1% CPU 사용량에 아주 잘 맞습니다)

그렇다면 여기서 부하가 발생하는 원인은 무엇입니까?

답변1

R 상태와 D 상태의 작업 모두 Linux 로드에 영향을 미치므로 이러한 상태 중 하나에서 시스템의 모든 스레드를 샘플링할 수 있습니다. 예를 들어:

for x in {1..100} ; do ps -aeos,user,comm,wchan | grep "^[RD]" ; sleep 0.1 ; done | sort | uniq -c | sort -nbr | head -20

ps아래 출력 예 에서는 모든 샘플링을 수행하는 프로세스이므로 항상 활성 상태인 자체 프로세스를 표시하는 맨 위 줄을 무시해야 합니다 .

# for x in {1..100} ; do
>   ps -aeos,user,comm,wchan | grep "^[RD]"
>   sleep 0.1
> done | sort | uniq -c | sort -nbr | head -20

    100 R root     ps              -
      3 R oracle   oracle_14047_li -
      2 R root     rcu_sched       rcu_gp_kthread
      2 R root     rcu_sched       -
      2 R root     kworker/1:2-eve -
      2 R oracle   perl            -
      2 R oracle   ora_vktm_lin19c hrtimer_nanosleep
      2 D root     md10_raid10     md_super_wait
      2 D oracle   ora_ckpt_linprd md_write_start
      1 R redis    redis-server    -
      1 R oracle   ora_vktm_linprd hrtimer_nanosleep
      1 R oracle   ora_m001_linprd -
      1 D root     xfsaild/dm-18   rq_qos_wait
      1 D oracle   ora_mz00_lin19c x64_sys_io_destroy
      1 D oracle   ora_lg00_lin19c inode_dio_wait
      1 D oracle   ora_dbrm_lin19c msleep

이전 커널에서 실행하지 않는 한, 최신 커널은 다른 사용자 프로세스의 WCHAN 값을 마스크하므로 이를 루트로 실행해야 합니다.

그보다 더 깊이 들어갈 수 있고(ps로는 불가능) 시스템 호출과 커널 스택 추적 정보도 샘플링 /proc/PID/syscall하고 얻을 수 있습니다. 이를 위해 /proc/PID/stackLinux Process Snapper( )라는 도구를 작성했으므로 psn커널 추적에 의존하지 않고도 이러한 성능 문제에 대해 상당히 고급 드릴다운을 수행할 수 있습니다.

[tanel@linux01 ~]$ sudo psn -G syscall,wchan

Linux Process Snapper v0.18 by Tanel Poder [https://0x.tools]
Sampling /proc/syscall, stat, wchan for 5 seconds... finished.


=== Active Threads ==========================================================================================

 samples | avg_threads | comm             | state                  | syscall         | wchan                 
-------------------------------------------------------------------------------------------------------------
     511 |      255.50 | (kworker/*:*)    | Disk (Uninterruptible) | [kernel_thread] | blkdev_issue_flush 
     506 |      253.00 | (oracle_*_l)     | Disk (Uninterruptible) | pread64         | do_blockdev_direct_IO 
      28 |       14.00 | (oracle_*_l)     | Running (ON CPU)       | [running]       | 0                     
       1 |        0.50 | (collectl)       | Running (ON CPU)       | [running]       | 0                     
       1 |        0.50 | (mysqld)         | Running (ON CPU)       | [running]       | 0                     
       1 |        0.50 | (ora_lgwr_lin*c) | Disk (Uninterruptible) | io_submit       | inode_dio_wait        
       1 |        0.50 | (oracle_*_l)     | Disk (Uninterruptible) | pread64         | 0                     
       1 |        0.50 | (oracle_*_l)     | Running (ON CPU)       | [running]       | SYSC_semtimedop       
       1 |        0.50 | (oracle_*_l)     | Running (ON CPU)       | [running]       | read_events           
       1 |        0.50 | (oracle_*_l)     | Running (ON CPU)       | read            | 0                     
       1 |        0.50 | (oracle_*_l)     | Running (ON CPU)       | semtimedop      | SYSC_semtimedop       

그보다 훨씬 더 깊이 들어갈 수 있습니다. 관련 블로그 항목은 다음과 같습니다.

답변2

CPU 사용량과 로드는 서로 다른 측정항목입니다. 실제로 로드는 1보다 클 수 있습니다. CPU는 CPU가 사용하는 실시간이므로 항상 100%보다 작아야 합니다(그러나 다중 코어/CPU에서는 이해가 되겠지만). 로드는 로드를 나타냅니다. 즉, 실행 중이고 실행 대기 중인 프로세스 수입니다.

(귀하의 질문에 대한 논의에서) 아시다시피 I/O는 일반적으로 그러한 대기 중 하나이므로 로드가 증가합니다. 그러나 대기를 유발할 수 있는 신호/세마포어/잠금도 있을 수 있으며 이는 I/O를 수행하지 않는 하나의 프로세스로 인해 발생할 수 있습니다. 예를 들어, 매초마다 하나의 프로세스가 깨어나고 해당 프로세스의 데이터를 기다리는 프로세스가 많으면 로드가 더 높아집니다(대기 중인 프로세스 수와 동일).

파이프는 I/O로 볼 수 있지만 mmap과 잠금은... IO로 분류됩니까? 바이오(블록 I/O)에는 표시되지 않으므로 많은 로드 통계에서는 표시되지 않을 수 있습니다.

이를 알아내는 더 쉬운 방법은 프로세스를 차단하고 프로세스가 어디에 있는지 확인하는 것입니다. 여러 번 수행하면 한 기능이 차단되는 것을 볼 수 있을 것입니다(그리고 다른 기능보다 훨씬 자주 발견될 수도 있습니다).

답변3

대략 450MHz의 i.mx28에서 실행되는 임베디드 시스템에서도 동일한 문제가 발생했습니다.

htop작업 중 하나로 인해 지속적으로 50%의 CPU 사용량이 표시되었습니다 swupdate.

mongoose_interface.c100ms 관찰을 탐색할 때 다음의 끝 부분에서 이것을 읽을 때 트리거됩니다 start_mongoose().

                mg_mgr_poll(&mgr, 100);

실험적으로 100을 1000으로 변경했고 다시 컴파일하고 다시 시작한 후 CPU 사용량 swupdatehtop.

말했듯이, 숫자가 너무 많은 우연의 일치라고 생각했기 때문에 이것은 실험적이었습니다. 부작용이 발생하는지 조사하지 않았습니다.

관련 정보