3

UDP パケットを受信する (送信なし) GTKmm Windows アプリケーション (MinGW で構築) があります。ソケットはネイティブの winsock で、glibmm IOChannel を使用してアプリケーションのメイン ループに接続します。ソケットは recvfrom で読み取られます。

私の問題は、このセットアップが 3 GHz ワークステーションで 25% の CPU 時間を消費することです。誰かが理由を教えてもらえますか?

この場合、アプリケーションはアイドル状態であり、UDP コードを削除すると、CPU 使用率がほぼゼロに低下します。アプリケーションは CPU を集中的に使用するタスクを実行する必要があるため、その 25% を費やすより良い方法を想像できます。

ここにいくつかのコードの抜粋があります: (printf で申し訳ありません ;) )


/* bind */
void UDPInterface::bindToPort(unsigned short port)
{
    struct sockaddr_in target;
    WSADATA wsaData;

    target.sin_family = AF_INET;
    target.sin_port = htons(port);
    target.sin_addr.s_addr = 0;

    if ( WSAStartup ( 0x0202, &wsaData ) )
    {
        printf("WSAStartup failed!\n");
        exit(0); // :)
        WSACleanup();
    }

    sock = socket( AF_INET, SOCK_DGRAM, 0 );
    if (sock == INVALID_SOCKET)
    {
        printf("invalid socket!\n");
        exit(0);
    }

    if (bind(sock,(struct sockaddr*) &target, sizeof(struct sockaddr_in) ) == SOCKET_ERROR)
    {
        printf("failed to bind to port!\n");
        exit(0);
    }

    printf("[UDPInterface::bindToPort] listening on port %i\n", port);
}

/* read */
bool UDPInterface::UDPEvent(Glib::IOCondition io_condition)
{
    recvfrom(sock, (char*)buf, BUF_SIZE*4, 0, NULL, NULL);
    /* process packet... */
}

/* glibmm connect */
Glib::RefPtr channel = Glib::IOChannel::create_from_win32_socket(udp.sock);
Glib::signal_io().connect( sigc::mem_fun(udp, &UDPInterface::UDPEvent), channel, Glib::IO_IN );

私はここで他の質問を読んだことがあります。また、ソケットが非ブロックモードになっていることを glib ドキュメント (g_io_channel_win32_new_socket()) で読んだことがあります。これは「実装の副作用であり、避けられない」ものです。これで CPU 効果が説明できますか?

パケットが到着する前に CPU が使い果たされ、読み取りハンドラーが呼び出されるため、glib を使用してソケットにアクセスするか、recvfrom() を直接呼び出すかどうかは、大きな違いはないようです。また、glibmm ドキュメントでは、ソケットがポーリングされていても recvfrom() を呼び出しても問題ないと述べています (Glib::IOChannel::create_from_win32_socket())。

-pg を使用してプログラムをコンパイルし、gprof を使用して関数ごとの CPU 使用率レポートを作成してみました。時間は私のプログラムではなく、外部の glib/glibmm dll で費やされているため、これは役に立ちませんでした。

4

0 に答える 0