-1

クライアントとサーバーの両方のように機能するソケットプログラムがあります。

入力ポートで接続を開始し、そこからデータを読み取ります。リアルタイムシナリオでは、入力ポートでデータを読み取り、データを(レコードごとに)出力ポートに送信します。

ここでの問題は、出力ポートにデータを送信している間、CPU使用率が50%に増加する一方で、許容されないことです。

while(1)
{    
        if(IsInputDataAvail==1)//check if data is available on input port
        { 
           //condition to avoid duplications while sending
        if( LastRecordSent < LastRecordRecvd )   
        {     
           record_time temprt;
           list<record_time> BufferList;
           list<record_time>::iterator j;
           list<record_time>::iterator i;

           // Storing into a temp list
            for(i=L.begin(); i != L.end(); ++i)
             {
               if((i->recordId > LastRecordSent) && (i->recordId <= LastRecordRecvd))
               {     
                temprt.listrec = i->listrec;
                temprt.recordId = i->recordId;
                temprt.timestamp = i->timestamp;
                BufferList.push_back(temprt);
               }
             }

                //Sending to output port
             for(j=BufferList.begin(); j != BufferList.end(); ++j)
             {
               LastRecordSent = j->recordId;

              std::string newlistrecord = j->listrec;
              newlistrecord.append("\n");
              char* newrecord= new char [newlistrecord.size()+1];
              strcpy (newrecord, newlistrecord.c_str());

             if ( s.OutputClientAvail() == 1) //check  if output client is available
             { 
              int ret = s.SendBytes(newrecord,strlen(newrecord));                        
              if ( ret < 0)
               { 
                log1.AddLogFormatFatal("Nice Send Thread : Nice Client Disconnected");    
                 --connected;
                  return;
               }                                              
            }
            else
            {
             log1.AddLogFormatFatal("Nice Send Thread : Nice Client Timedout..connection closed");    
             --connected; //if output client not available disconnect after a timeout
             return;
            }                                        
          }    

       }  
      }

    //  Sleep(100); if we include sleep here CPU usage is less..but to send data real time I need to remove this sleep.
If I remove Sleep()...CPU usage goes very high while sending data to out put port.          
  }//End of while loop

リアルタイムのデータ転送を維持し、CPU使用率を削減するための可能な方法。提案してください。

4

2 に答える 2

0

リストされたコードには2つの潜在的なCPUシンクがあります。まず、外側のループ:

while (1)
{
    if (IsInputDataAvail == 1)
    {
        // Not run most of the time
    }

    // Sleep(100);
}

Sleep呼び出しによってCPU使用率が大幅に削減されることを考えると、このスピンループが原因である可能性が最も高くなります。IsInputDataAvail別のスレッドによって設定された変数のように見えます(プリプロセッサマクロの場合もあります)。これは、そのCPUのほとんどすべてがこの1つの比較命令と2つのジャンプの実行に使用されていることを意味します。

その無駄な電力を取り戻す方法は、入力が利用可能になるまでブロックすることです。読み取りスレッドはおそらくすでにそうしているので、出力スレッドをブロックするシステムコールを使用して、2つの間で通信するためのある種のセマフォが必要です。利用可能な場合、理想的なオプションはsem_wait()、ループの最上部にある出力スレッドと、sem_post()現在設定されている入力スレッドにありますIsInputDataAvail。それが不可能な場合は、代わりにセルフパイプトリックが機能する可能性があります。

2番目の潜在的なCPUシンクはにありs.SendBytes()ます。肯定的な結果がレコードが完全に送信されたことを示す場合、そのメソッドはループを使用している必要があります。おそらくブロッキング呼び出しを使用してレコードを書き込みます。そうでない場合は、そうするように書き直すことができます。

または、アプリケーションの半分を書き直して、、、または同様の方法を使用select()poll()て読み取りと書き込みを同じスレッドにマージすることもできますが、プログラムがすでにほぼ完了している場合は、それは非常に手間がかかります。

于 2012-10-28T08:51:37.337 に答える
0
  if(IsInputDataAvail==1)//check if data is available on input port

それを取り除きます。入力ポートから読み取るだけです。データが利用可能になるまでブロックされます。これは、CPU 時間のほとんどが使用される場所です。ただし、他にも問題があります。

          std::string newlistrecord = j->listrec;

ここでは、データをコピーしています。

          newlistrecord.append("\n");

          char* newrecord= new char [newlistrecord.size()+1];
          strcpy (newrecord, newlistrecord.c_str());

ここでは、同じデータを再度コピーしています。また、メモリを動的に割り当てており、メモリもリークしています。

         if ( s.OutputClientAvail() == 1) //check  if output client is available

これが何をするのかわかりませんが、削除する必要があります。次の送信は、エラーをチェックする時間です。未来を推測しようとしないでください。

          int ret = s.SendBytes(newrecord,strlen(newrecord));

ここでは、設定した時点でおそらくすでに知っていた文字列の長さを再計算していますj->listrecs.sendBytes()これをすべて行うよりも、 を直接呼び出してj->listrecからもう一度 を呼び出す方がはるかに効率的"\n"です。いずれにせよ、TCP はデータを結合します。

于 2014-10-30T02:14:19.800 に答える