clientA から clientB、clientC、clientD などにファイルをリレーするサーバー アプリケーションがあります。この種のファイル リレーをタスクと呼びます。実行中のタスクが多数ある場合、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() の 3 つのステップはすべて CPU を集中的に使用する操作です。このような操作で CPU 使用率をできるだけ下げる方法はありますか (この方法を除く: "char buffer[1024]" などの非常に小さなバッファー サイズを設定します)。
ここでの問題は、アプリケーションが同じマシン上で別のサーバー アプリケーションと一緒に実行されるため、FileRelayer アプリケーションが CPU を消費しすぎないことです。そうしないと、他のサーバー アプリケーションが正常に動作しません。
[更新]
アプリケーションに関するいくつかの情報は次のとおりです
。 A. この FileServer マルチスレッド サーバー アプリケーションには約 70 のスレッドがありますが、すべてのソケットからデータを受信するために使用されるのはそのうちの 1 つだけです。
B. リスニング ソケットを含むすべてのソケットがノンブロッキング モードである。
C. アプリケーションが 4 つのクライアント (4 つのソケット) から 200 メガの 4 つのファイルを受信しているときに、高い CPU 使用率 (80% - 90%) が検出されました。
問題について:
受信フロー全体を 2 つの主要な部分に分け、それらを FlowA と FlowB と呼びます。FlowA はソケットからデータを受信するだけです。FlowB は receive_data() でデータを処理する部分 (パケットのスライスなど) を表します。FlowA と FlowB はそれぞれ CPU 使用率が高くなることがわかりました。
1) FlowA: スタックから割り当てられた大きな配列 (1 メガ)、この投稿で示されています。私たちのテストでは、FlowA (ソケットからデータを受信した後にデータを破棄する) のみを残し、CPU 使用率が長時間にわたって 80 ~ 90% の高さに留まっていることがわかりました。そして、「char Buffer[ONE_MEGA]」を「char *buffer = new char[ONE_MEGA]」に置き換えると、CPU 使用率は 14% に減少します。
2) FlowA + FlowB: FlowA の問題を解決した後、今回は変動はあるものの、フロー全体 (FlowA + FlowB) で CPU 使用率が依然として 80% と高いことがわかりました。
受信バッファを char buffer[1024] などの非常に小さいものに設定すると、関数呼び出しごとに 1 つまたは 2 つのパケットしか処理しないため、CPU 使用率は劇的に減少しますが、転送速度も低下することが懸念されました。この問題を解決する他の方法はありますか?</p>