0

以下のコードは機能し、正しいデータをすべて送信し、正しいデータを受信して​​います。

非常に高速なサーバーのベンチマークに使用すると、ベンチマークの CPU 使用率は ~10% です。ただし、遅いサーバーのベンチマークを行うと、ベンチマーク/ストレス テストを行っているサーバーと同じように、50% まで上昇します*。

それはtop報告しているとおりです。

なぜそんなに多くのCPUを使用するのでしょうか? poll を悪用していると思われますが、方法がわかりません。

低速サーバーの 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 経由です。)

4

3 に答える 3

1

その理由はあなたが忙しく待っているからです。readand writereturnEAGAINまたはEWOULDBLOCKあなたがそれらを継続的に呼び出している場合。selectその前に、ソケットが読み取りまたは書き込みの準備ができるまで待機するa を追加します。

于 2014-01-26T13:19:54.230 に答える
0

%CPUですから、私が最終的にこれを理解したとしたら、トップが報告した の比率とトップが報告した の増加率の比率を比較してTIME+いて、それらは一致していません。(どの列から読んでいるかを言った方が簡単だったでしょう!) 私が知る限り、両方とも基礎となる/procデータの同じフィールドから計算されているので、それらが大きく反対することはあり得ないはずです.

そして、私はそれを複製することはできません。私はあなたのコードをテスト プログラムに入れ、int rコンパイル エラーの再宣言を修正し、あなたが除外したすべてのものに対して妥当な宣言であると思われるものを追加する以外は、何も変更せずに実行しました。私はそれをサーバーに接続しました。サーバーはクライアントから行を読み取り、1行ごとにCPUを少し消費してから行を送り返します。その結果、top は%CPUサーバーで約 99、クライアントで 2 で、TIME+列の比率は約 50 対 1 でした。

の使用に問題はありませんpoll

ただし、あなたの使用は好きではありませんassert-アサーションがオフになっていると、プログラムは多くの重要なシステムコールを見逃すことになります.

于 2014-01-26T17:33:52.797 に答える
0

問題が解決しました。

CPU使用率が正確に誤って伝えられたわけではありません。非効率的なサーバーは TCP_NODELAY を使用して 8 バイトのパッケージを送信していたため、わずか 8 バイトを読み取るために何百万ものポーリング通知を受信して​​いました。read(2) 呼び出しはかなり高価であることが判明し、1 秒あたり数万回呼び出しただけで、「システム モードで費やされた時間」が 56% まで急上昇し、「ユーザー モードで費やされた時間」に追加されました。 " 非常に高い CPU 使用率を生成します。

于 2014-01-26T14:37:32.883 に答える