CPU 사용량이 1%인 프로세스의 로드 평균은 1.5입니다.

CPU 사용량이 1%인 프로세스의 로드 평균은 1.5입니다.

에 따르면 거의 모든 프로세스가 절전 모드에 있어야 함에도 불구하고 최근 임베디드 시스템의 로드 평균이 약 1.5에 달하는 것을 확인했습니다 htop.

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

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

time응용 프로그램의 평균 CPU 사용량을 추정 할 때 (계산하여)(사용자+시스템)/실제), 내가 얻는 값은 약 1%에 불과하며, 이는 로드 평균 1.5를 고려하면 큰 의미가 없습니다.

TASK_UNINTERRUPTIBLE로드 평균 에는 CPU 사용량에 영향을 주지 않는 해당 상태의 프로세스 도 포함된다는 것을 이해합니다 . 내가 이해하지 못하는 것은 애플리케이션의 스레드/프로세스가 왜 그 상태에 있는지입니다.

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

이는(100밀리초마다): 여기에 이미지 설명을 입력하세요.

보시다시피 소켓 기반 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하고 얻을 수도 있습니다. 이를 위해 Linux Process Snapper( )라는 도구를 /proc/PID/stack작성했기 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에서 실행되는 임베디드 시스템에서도 동일한 문제가 발생했습니다.

htopCPU 사용량이 계속 50%로 표시되는데, 이는 전적으로 작업 중 하나로 인해 swupdate발생합니다 .

100ms 관찰을 탐색하는 동안 mongoose_interface.c다음을 읽으면 실행하십시오 start_mongoose().

                mg_mgr_poll(&mgr, 100);

실험적으로 100을 1000으로 변경해 보았는데, 다시 컴파일하고 재시작한 후에 swupdatehtop.

언급한 바와 같이, 숫자가 너무 우연적이라고 생각하기 때문에 이것은 실험적입니다. 부작용이 발생하는지 조사하지 않았습니다.

관련 정보