2014-01-26 5 views
0

아래의 코드가 작동합니다. 올바른 데이터를 모두 전송하고 있으며 올바른 데이터를 수신하고 있습니다.왜 이러한 벤치 마크 코드는 높은 CPU를 사용합니까?

매우 빠른 서버를 벤치 마크 할 때 벤치 마크의 CPU 사용량은 ~ 10 %입니다. 그러나 느린 서버를 벤치마킹 할 때 ~ 50 %로 상승합니다. 서버 벤치마킹/스트레스 테스트 *와 동일합니다.

그게 무슨 일이냐고 top 님의보고입니다.

왜 CPU를 많이 사용합니까? 나는 여론 조사를 잘못하고 있다고 생각하지만 어떻게 확신 할 수 없습니까?

느린 서버의 CPU 시간은 벤치 마크의 4 배이며 빠른 서버의 경우 벤치 마크의 7 배입니다.

int flags = fcntl(sockfd, F_GETFL, 0); 
assert(flags != -1); 
assert(fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) != -1); 

int32 red = 0; 
struct pollfd pollfd = { 
    .fd = sockfd, 
    .events = POLLIN | POLLOUT 
}; 
do { 
    assert(poll(&pollfd, 1, -1) == 1); 
    if (pollfd.revents & POLLOUT) { 
     int n; 
     while ((n = send(sockfd, buf__+bufOffset, bufLength-bufOffset, MSG_NOSIGNAL)) > 0) { 
      bufOffset += n; 
      if (n != bufLength-bufOffset) 
       break; 
     } 
     assert(!(n == -1 && errno != EAGAIN && errno != EWOULDBLOCK)); 
    } 

    if (pollfd.revents & POLLIN) { 
     int r; 
     while ((r = read(sockfd, recvBuf, MIN(recvLength-red, recvBufLength))) > 0) { 
      // assert(memcmp(recvBuf, recvExpectedBuf+red, r) == 0); 
      red += r; 
      if (r != MIN(recvLength-red, recvBufLength)) 
       break; 
     } 
     assert(!(r == -1 && errno != EAGAIN && errno != EWOULDBLOCK)); 
    } 
} while (bufOffset < bufLength); 

assert(fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK) != -1); 
int r; 
while ((r = read(sockfd, recvBuf, MIN(recvLength-red, recvBufLength))) > 0) { 
    // assert(memcmp(recvBuf, recvExpectedBuf+red, r) == 0); 
    red += r; 
} 
assert(fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) != -1); 

assert(red == recvLength); 

int r = read(sockfd, recvBuf, 1); 
assert((r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) || r == 0); 

*는 (나는 지금, 동일한 시스템에서 모두 벤치 마크 및 서버를 실행하고 있습니다. 통신은 TCP 이상입니다.)

+0

나는 정말로 그 질문을 이해하지 못한다 ... 만약 당신이 더 강력한 컴퓨터를 가지고 있다면, 그것은 로우 엔드 컴퓨터보다 대용량 데이터를 더 쉽게 처리 할 것임이 분명하다. 어느 것이 끝날 수 있는가? "고성능"컴퓨터에서 더 빨리 끝내거나 "한 번"으로 끝내지 만 낮은 성능에서는 더 많은 CPU를 사용한다. – Reinherd

+0

@ SergiCastellsaguéMillán 모두 동일한 컴퓨터에 있으며 모두 동일한 CPU 코어에 있습니다."느린 서버"와 "빠른 서버"의 유일한 차이점은 하나의 코드베이스가 오버 헤드가 많은 부피가 큰 느린 코드베이스이고, 하나는 새롭고 가벼운 재 작성이라는 것입니다. – Max

+0

전체 메시지 후에 만 ​​서버가 응답합니까? 그렇다면 ... –

답변

1

이유는 당신이 바쁜 대기 때문이다. readwrite이 (가) EAGAIN 또는 EWOULDBLOCK을 반환하면 계속해서 전화를 걸 수 있습니다. select을 추가하면 소켓이 읽기 전이나 쓰기 전까지 대기합니다.

+0

나는 생각하지 않는다. while 루프는 반환 값이> 0이고 'do ... while' 루프에 폴이있을 때만 계속된다. – Max

+0

그렇지만 fd가 읽기 준비가되었거나 쓰기 준비가되면 리턴됩니다. 당신은 각각 하나씩 기다리기를 원합니다. 나는'select'를 사용 하겠지만'poll'은 괜찮을 것이라고 생각합니다. – abligh

+0

방금 ​​고려해야 할 코드를 업데이트했습니다. 아아, 여전히 50 %의 CPU 사용량입니다. – Max

0

문제가 해결되었습니다.

정확하게 CPU 사용을 잘못 표시하지 않았습니다. 비효율적 인 서버는 TCP_NODELAY가있는 8 바이트 패키지를 보내고 있었으므로 수백만 개의 폴링 알림을 수신하여 8 바이트 만 읽었습니다. read (2) 호출은 비용이 많이 들었고 초당 수만 번을 호출하면 "시스템 모드에서 보낸 시간"로켓을 ~ 56 %까지 볼 수있었습니다.이 값은 "사용자 모드에서 소비 된 시간"에 추가되었습니다 "매우 높은 CPU 사용량을 생성합니다.

+0

완벽한 말도 안돼. 프로세스가'poll'에서 막히면, 유휴 상태로 계산되지 않습니다. –

+0

@ WumpusQ.Wumbley 무엇이 내가 벤치 마크의 10 가지 인스턴스를 동시에 실행할 수 있다고 결론 내렸고,보고 된 CPU 사용량이 각각 줄어들었다. 그래서 서버는 ~ 50 %를 소비하게 될 것이며 각 벤치 마크는 ~ 5 %를 소비하게 될 것입니다. 나는 대략 위의 것 이외에 이것을 설명 할 어떤 설명도 짐작할 수 없다. – Max

+0

동일한 시스템에서 클라이언트와 서버를 실행 중이므로 네트워크 지연이 없습니다. 서버가 클라이언트에 쓰는 것 이외의 작업에서 블로킹하지 않으면 총 CPU 사용량이 100 % 미만이 될 이유가 없습니다. 그리고 서버가 클라이언트에게 보내는 응답을 생성하기 위해 많은 CPU를 필요로하지 않는다면, 부서가 50 % 서버이고 클라이언트가 50 %가 분할되지 않을 이유는 없습니다. 그래서 당신이 기대 한 것은 무엇이며, 그 이유는 무엇입니까? –

0

결국 이것을 이해하면 TIME+의 증가율의 비율과 상단에서보고 한 %CPU의 비율을 비교하는 것이므로 동의하지 않습니다. (어떤 열을 읽었는지 말하면 더 쉬울 것입니다!) 내가 알 수있는 한 두 가지 모두는 기본 데이터 인 /proc의 동일한 필드에서 계산되므로 많은 사람들이 동의하지 않아야합니다.

그리고 그것을 복제 할 수 없습니다. 나는 당신의 코드를 테스트 프로그램에 넣고 int r 컴파일 에러의 재 선언을 수정하는 것 외에 수정하지 않고 실행했다. 당신이 버린 모든 것들에 대한 합리적인 선언이라고 생각하는 것을 추가한다. 클라이언트에서 줄을 읽는 서버에 연결하고 줄을 보내기 전에 각 줄마다 CPU를 조금씩 먹습니다. 결과는 서버의 경우 %CPU 약 99, 클라이언트의 경우 2, TIME+ 열의 약 50 대 1 비율을 나타냅니다.

poll의 사용에는 아무런 문제가 없습니다.

어쨌든 assert을 사용하는 것을 좋아하지 않습니다. 어설 션을 끄면 중요한 syscalls가 많이 누락 될 것입니다.

+0

도와 줘서 고마워, Wumpus. epoll을 사용하여 다시 썼는데, 같은 문제 만있었습니다. 그런 다음 각 섹션에서 소요되는 시간을 측정하기 시작했고 'do ... while' 루프를 반복해야한다는 것을 깨달았습니다. 느린 서버는 8 바이트 패키지를 출력하고 있었고, 모든 단일 패키지에 대해 알 렸습니다. 모든 단일 패키지에 대해 read (2)를 호출했습니다. 읽기의 시스템 오버 헤드로 인해 CPU 시간이 길어졌습니다. – Max