우리는 clientA에서 clientB, clientC, clientD 등의 파일을 중계하는 서버 응용 프로그램을 가지고 있습니다. 우리는 이러한 종류의 파일 중첩을 작업으로 부릅니다. 실행중인 작업이 많으면 CPU 사용량이 매우 높습니다.FileServer에서 높은 CPU 사용을 피할 수 있습니까?
여러 개의 작업을 동시에 실행하는 것과 같은 높은 CPU 사용 현상은 정상적인 것인지 아닌지 궁금합니다. 이러한 종류의 응용 프로그램에서 CPU 사용을 줄이는 방법이 있습니까?
//pseudo code
void service(void){
while(1){
....
struct timeval timeout;
timeout.tv_sec = 3;
...
ret = select(maxFd+1, &read_set, NULL, NULL, &timeout);
if (ret > 0){
//get socket from SocketsMap
//if fd in SocketsMap and its being set
//then receive data from the socket
**all fd are in non-blocking mode**
receive_data(fd);
}
}
}
void receive_data(int fd){
const int ONE_MEGA = 1024 * 1024;
char *buffer = new char[ONE_MEGA];
int readn = recv(fd, buffer, ONE_MEGA, 0);
//handle the data: many steps
char* DataToProcess = buffer;
int LenToProcess = readn;
while(LenToProcess > 0){
1. scan the data to find the packet header
2. get the length from the packet then perform checksum
function which will scan every character of the packet
to get a checksum value.
3. if the packet is valid then add the packet to data queue.
Move the buffer pointer and process the remaining data.
......
LenToProcess -= DataProcessed;
DataToProcess += DataProcessed;
};
}
여기서 알 수 있듯이, receive_data()의 세 단계는 모두 CPU 집약적 인 작업입니다. 거기에 이런 종류의 작업 (가능하면 "char buffer [1024]"와 같은 매우 작은 버퍼 크기 설정)에서 CPU 사용량을 가능한 줄일 수있는 방법이 있습니까?
여기에서 우리의 응용 프로그램은 동일한 시스템에서 다른 서버 응용 프로그램과 함께 실행되므로 FileRelayer 응용 프로그램은 너무 많은 CPU를 소비 할 수 없으며 다른 서버 응용 프로그램은 정상적으로 작동하지 않습니다.
[UPDATE] 여기서
어플리케이션에 대한 정보의 일부 조각이다 :
A.가 모든 데이터를 수신하기 위해 사용되는 약 70이 파일 서버 스레드 서버 애플리케이션의 스레드 만, 이들의 하나는 소켓.
B. 모든 소켓은 수신 소켓을 포함하여 비 차단 모드입니다.
C. 응용 프로그램이 4 개의 클라이언트 (4 소켓)에서 200 메가의 파일 4 개를 수신하는 동안 높은 CPU 사용률 (80 % - 90 %)이 발견되었습니다. 이 문제에 관해서는
:
우리는 두 개의 주요 부분으로 전체 수신의 흐름을 분리, FlowA 및 FlowB를 호출 할 수 있습니다. FlowA는 소켓에서 데이터 만 수신합니다. FlowB는 패킷 분할과 같이 receive_data()에서 데이터를 처리하는 부분을 의미합니다. FlowA가 발견되어 FlowB가 각각 cpu 사용량을 높일 수 있습니다.
1) FlowA : 스택에서 할당 한 큰 배열 (1 메가), this post에 의해 분산 됨. 우리의 테스트에서는 FlowA (소켓에서 데이터를받은 후 데이터를 버립니다) 만 남겨두고 오랜 시간 동안 CPU 사용량이 80-90 %로 높습니다. 그리고 "char 버퍼 [ONE_MEGA]"를 "char * buffer = new char [ONE_MEGA]"로 대체하면 CPU 사용률이 14 %로 감소합니다.
2) FlowA + FlowB : FlowA의 문제를 해결 한 후에 전체 Flow (FlowA + FlowB)에서 CPU 사용량이 여전히 80 %로 높은 것으로 나타났습니다.
수신 버퍼를 char 버퍼 [1024]와 같이 매우 작게 설정하면 각 함수 호출에서 하나 또는 두 개의 패킷 만 처리하기 때문에 CPU 사용량이 크게 줄어들지 만 전송 속도 또한 저하 될 것이라고 걱정합니다 . 그래서이 문제를 해결할 다른 방법이 있습니까?
높은 부하에서 높은 CPU 사용률이 실제로 좋습니다. 처리 알고리즘이 매우 비효율적이지 않으면 높은 사용량은 대기 시간이 거의 없음을 의미합니다. – dasblinkenlight
@dasblinkenlight CPU 사용의 핵심을 지적 해 주셔서 감사합니다. ariticle을 업데이트했습니다. – Steve
코드의 어느 부분이 더 큰 버퍼로 실제로 시간을 소비하는지 알아보십시오. 예를 들어 Linux에서'oprofile' 또는'perftool'을 사용하여 코드의 병목 현상을 확인할 수 있습니다. –