cpu 부하 연구
1.cpu 부하의 정의
우선, cpu 부하의 정의를 보십시오.일반적인 상황에서 단일 핵심 cpu의 부하를 단일행 다리로 볼 수 있다. 숫자 1은 cpu가 마침 처리할 수 있다는 것을 의미한다. 즉, 다리 위에서 모든 차량을 순조롭게 통과할 수 있다는 것이다.
다리 밖에는 기다리는 차량이 없어서 다리가 잘 통한다.1이 넘으면 다리에 오르기를 기다리는 차량이 있고, 1보다 작으면 차량이 빠르게 통과할 수 있다는 뜻이다.단일 핵심 cpu는 이 cpu가 처리할 수 있는 사무 수가 1이고 다중 핵에 있음을 나타낸다
cpu에서 cpu가 병행 처리할 수 있는 업무의 수량은 cpu 개수 *cpu 핵수이며, 부하 수는 이 수치를 초과하지 않는 것이 가장 좋다.예를 들어 4코어 cpu는 cpu_load의 최대치는 4로 장기적으로 4를 초과할 수 없습니다. 그렇지 않으면 작업이 제때에 처리되지 않아 시스템의 부하 누적을 높여 시스템 운행이 느려집니다.
대부분의 유닉스 시스템의 부하는 실행 상태와 실행 가능한 상태를 기록하는 것뿐이지만, 리눅스는 다르다. 이것은 중단할 수 없는 수면 상태의 프로세스를 포함한다.이 때 이 프로세스들이 I/O의 장애로 인해 실행되지 못하면 cpu의 부하를 현저하게 증가시킬 수 있습니다.따라서 유닉스와 리눅스에 있는 cpu의 부하 계산 방법은 다르고 모니터링 값을 설정할 때도 특별 시험률이 필요하다.
다음은 내부 원본 코드에서 cpu 부하의 계산 근원을 분석하고 여기서 cpu 부하의 완전한 계산 방법을 제시할 수 있다.다음 코드는kernel-2.6.32의kernel/shed입니다.c에서 캡처한 것은 cpu의 평균 부하를 계산하는 데 쓰인다.
/* Variables and functions for calc_load */
static atomic_long_t calc_load_tasks;
static unsigned long calc_load_update;
unsigned long avenrun[3];
EXPORT_SYMBOL(avenrun);
/**
* get_avenrun - get the load average array
* @loads:pointer to dest load array
* @offset:offset to add
* @shift:shift count to shift the result left
*
* These values are estimates at best, so no need for locking.
*/
void get_avenrun(unsigned long *loads, unsigned long offset, int shift)
{
loads[0] = (avenrun[0] + offset) << shift;
loads[1] = (avenrun[1] + offset) << shift;
loads[2] = (avenrun[2] + offset) << shift;
}
static unsigned long
calc_load(unsigned long load, unsigned long exp, unsigned long active)
{
load *= exp;
load += active * (FIXED_1 - exp);
return load >> FSHIFT;
}
/*
* calc_load - update the avenrun load estimates 10 ticks after the
* CPUs have updated calc_load_tasks.
*/
void calc_global_load(void)
{
unsigned long upd = calc_load_update + 10;
long active;
if (time_before(jiffies, upd))
return;
active = atomic_long_read(&calc_load_tasks);
active = active > 0 ? active * FIXED_1 : 0;
avenrun[0] = calc_load(avenrun[0], EXP_1, active);
avenrun[1] = calc_load(avenrun[1], EXP_5, active);
avenrun[2] = calc_load(avenrun[2], EXP_15, active);
calc_load_update += LOAD_FREQ;
}
/*
* Either called from update_cpu_load() or from a cpu going idle
*/
static void calc_load_account_active(struct rq *this_rq)
{
long nr_active, delta;
nr_active = this_rq->nr_running; // cpu
nr_active += (long) this_rq->nr_uninterruptible; //
if (nr_active != this_rq->calc_load_active) {
delta = nr_active - this_rq->calc_load_active;
this_rq->calc_load_active = nr_active;
atomic_long_add(delta, &calc_load_tasks);
}
}
위의 코드, 특히 주석의 두 줄에서 알 수 있듯이 Linux가 cpu 부하를 기록할 때 cpu 대기열의 운행 프로세스 수와 중단 불가능한 프로세스 수를 모두 통계하여 cpu 부하를 분석할 때 중단 불가능한 프로세스의 상황을 고려해야 한다
2. cpu 부하에 영향을 주는 프로세스
정의에서 알 수 있듯이 cpu의 부하는 주로 cpu에서 실행되는 프로세스 수, 대기열에 준비된 프로세스 수와 중단할 수 없는 프로세스 수 (Linux에 중단할 수 없는 프로그램을 추가하고 UNIX라면 추가하지 않음) 에서 나온다.그러면 cpu 부하가 너무 높을 때 현재 실행 중인 프로세스의 상태를 알 수 있다면 어떤 프로세스의 운행이 문제를 일으켰는지 판단할 수 있습니다.마침 Linux에서 ps는 현재 실행 중인 프로세스의 상태를 찾는 데 도움을 줄 수 있습니다. 이 프로세스의 상태에 대한 이해를 통해 문제의 진정한 원인을 잘 찾을 수 있습니다.
#ps aux는 프로세스의 실행 상태를 표시합니다.
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
ps aux를 사용하면 하나의 프로세스의 11가지 파라미터를 알 수 있습니다. 그 중에서 STAT는 프로세스의 운행 상태를 표시합니다.
프로세스의 상태는 다음과 같습니다.
================ 프로세스 STAT 상태 =====================
D 중단할 수 없는 휴면 상태(일반 입출력 프로세스)
R이 실행 중입니다. 중단 가능한 대기열에 있습니다.
S는 휴면 상태, 정지 상태;
T가 정지되거나 추적되어 실행을 정지합니다.
W가 메모리 교환에 들어간다(코어 2.6부터 무효).
X가 죽는 과정;
Z좀비 프로세스가 존재하지 않지만 잠시 제거할 수 없습니다.
W:메모리 페이지를 할당할 수 있는 충분한 메모리가 없습니다
WCHAN이 기다리고 있는 프로세스 자원;
<:>
N: 낮은 우선 순위 프로세스
L:메모리가 페이지별로 분배되어 메모리에 잠긴다(인스턴트 시스템 또는 A I/O). 즉, 일부 페이지는 메모리에 잠긴다
s 프로세스의 지도자(그 아래에 하위 프로세스가 있음).
l 다중 프로세스의(CLONE_THREAD, NPTL pthreads와 유사)
+ 백그라운드에 있는 프로세스 그룹;
3. cpu의 과부하를 방지하는 방법
단기적으로 볼 때kill과killall을 통해 cpu 부하에 영향을 주는 프로세스를 죽이고 cpu 부하를 낮추는 목적을 달성할 수 있다.
이러한 프로세스의 상태는 ps를 이용하여 표시할 수 있고 관련 프로세스에 대해 일정한 조치를 취하면 짧은 시간 안에 cpu의 부하를 낮출 수 있다.
킬과 킬의 용법에 관해서는 상세한 소개를 하지 않습니다.
4.cpu 부하가 너무 높은 진일보한 분석
장기적으로 보면 cpu의 부하가 높지 않으려면 cpu의 이용률과 현재의 서비스로 분석해야 한다.
다음은 구체적인 사례로 분석한다.
우리는 서버가 있는데 서버의 링크 수가 너무 높으면 nfs가 막힌다. (이 서버와 다른 서비스는 nfs로 파일을 공유한다.) 이때wa는 95.8%이고 부하는 곧 180으로 올라간다.
server1:~$ est
467 connections established
서버에 대량의 링크 수가 있을 때 nfs가 막히는 문제가 발생합니다.
root 2631 0.2 0.0 0 0 ? D Jul20 50:28 [nfsd]
root 2632 0.2 0.0 0 0 ? D Jul20 49:24 [nfsd]
root 2633 0.2 0.0 0 0 ? S Jul20 49:27 [nfsd]
root 2634 0.2 0.0 0 0 ? S Jul20 49:47 [nfsd]
root 2635 0.2 0.0 0 0 ? S Jul20 51:12 [nfsd]
root 2636 0.2 0.0 0 0 ? S Jul20 49:00 [nfsd]
root 2637 0.2 0.0 0 0 ? S Jul20 49:39 [nfsd]
root 2638 0.2 0.0 0 0 ? D Jul20 50:24 [nfsd]
server1:~$ top
top - 16:13:12 up 14 days, 21:21, 2 users, load average: 180.20, 59.85, 22.61
Tasks: 125 total, 1 running, 124 sleeping, 0 stopped, 0 zombie
Cpu : 2.3%us, 1.3%sy, 0.0%ni, 0.0%id, 95.8%wa, 0.0%hi, 0.5%si, 0.0%st
Mem: 2076212k total, 2028752k used, 47460k free, 1804k buffers
Swap: 2104472k total, 1089140k used, 1015332k free, 244076k cached
이런 간단한 분석을 통해 기본적으로 문제가 nfs에 있다고 단정할 수 있고 파일 공유 방식을 조정해야 한다.
5. cpu 부하와 이용률의 관계
여러분은 이곳의 문장 한 편을 참고하여 아주 잘 쓸 수 있습니다.
http://www.blogjava.net/cenwenchu/archive/2008/06/30/211712.html