为什么这个基准代码使用如此高的CPU?

时间:2014-01-26 13:01:00

标签: c linux posix poll-syscall

下面的代码有效,它发送所有正确的数据,并且它正在接收正确的数据。

当我使用它来测试非常快的服务器时,基准测试的CPU使用率约为10%。但是,当我对一台慢速服务器进行基准测试时,它会上升到~50% - 与我正在进行基准测试/压力测试的服务器相同*。

这是top报告的内容。

为什么会使用这么多CPU?我怀疑我在滥用民意调查,但我不确定如何?

慢速服务器的CPU时间是基准测试的4倍,而快速服务器的CPU时间是基准测试的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进行的。)

3 个答案:

答案 0 :(得分:1)

原因是你在忙着等待。如果readwrite返回EAGAINEWOULDBLOCK,则表示您正在连续调用它们。添加一个select,它将等待套接字准备好在此之前读取或写入。

答案 1 :(得分:0)

问题解决了。

并没有完全错误地表示CPU使用情况。效率低下的服务器使用TCP_NODELAY发送8字节包,所以我收到了数百万个轮询通知,只读取8个字节。事实证明,read(2)调用相当昂贵,并且每秒调用它数万次就足以看到“在系统模式下花费的时间”火箭达到~56%,这被添加到“用户模式花费的时间” “产生非常高的CPU使用率。

答案 2 :(得分:0)

因此,如果我最终理解了这一点,那么您要比较top报告的%CPU与top报告的TIME+增长率的比率,他们不同意。 (如果你说的是你正在阅读哪些列,那会更容易!)据我所知,两者都是从底层/proc数据中的相同字段计算的,所以它们不可能不同意见。

我无法复制它。我已将您的代码放入测试程序并运行它,除了修复int r编译错误的重新声明,并添加我认为对您遗漏的所有内容的合理声明。我将它连接到一个服务器,该服务器从客户端读取行并在每个行之后吃掉一点CPU,然后再发回一行。结果是,顶部显示%CPU约为99,服务器为2,客户端为2,TIME+列约为50:1。

我发现使用poll没有错。

我不喜欢你使用assert - 当断言被关闭时,程序会丢失许多重要的系统调用。