12

Linuxシステムで「cat」関数をシミュレートするためにシステムコール(open、read、write)を使用してCでこの関数を実行しましたが、実際の関数よりも低速です...

実際の「cat」と同じバッファサイズを使用しており、「strace」を使用しているので、同じ量のシステムコールが実行されていると思います。しかし、私の「猫」からの出力は、実際の「猫」よりも少し遅いです。

これは私が持っているコードです:

#define BUFSIZ 32768

int sysWriteBuffer(int fdout, char *buffer, ssize_t readBytes) {
    ssize_t writtenBytes = 0;

    while(writtenBytes < readBytes) {
        writtenBytes += write(fdout,
            buffer + writtenBytes, readBytes - writtenBytes);
        if(writtenBytes == -1) {
            return -1;
        }
    }

    return 0;
}

int catPrint(int fdin, int fdout) {
    char buffer[BUFSIZ];
    ssize_t readBytes;

    do {
        readBytes = read(fdin, buffer, BUFSIZ);

        if(readBytes == -1) {
            return -1;
        }

        if(sysWriteBuffer(fdout, buffer, readBytes) == -1) {
            return -1;
        }
    } while(readBytes > 0);

    return 0;
}

私はファイルから読み取っています(mainに引数として渡します。ここではコードは必要ないと思います)。そのファイル記述子と出力記述子に1を指定してcatPrint()関数を呼び出し、stdoutに出力します。

テストに同じファイルを使用していて、両方(実際の「猫」と私のもの)では、テキスト全体に対して1つのread()と1つのwrite()しかないため、なぜ遅くなるのかわかりません。テキスト全体を画面に表示するだけではいけませんか?

PS:ここでの私の質問(なぜ遅いのか)は宿題の一部ではありませんが、これを宿題としてタグ付けしました。システムコールを使用して「cat」タイプの関数を作成するだけで済みました。少し遅いコードに興味があります。

私からの愚かさで解決した問題:
同じファイルでLinuxの元の猫を次々と呼び出すことにしましたが、呼び出すときも同じくらい遅いことに気づきました。自分の。私はすべてがより良いと思います...

この人のように時間を無駄にしてすみません。

4

6 に答える 6

16

ああ、あなたの編集に基づいて、あなたは先読みバッファに噛まれていました。ファイルを並べて読み取る2つのプログラムを1回実行してテストすることはできません。ファイルがディスク上にあるため、最初のデータは常に遅くなります。ファイルがメモリに入ると、2番目のデータの実行速度が速くなります。それぞれに新しいデータを作成するか、1つを実行してから両方を実行して、両方が先読みバッファのメリットを享受できるようにする必要があります。

于 2009-04-20T19:38:33.737 に答える
3

おそらく、最適化なしで(または最適化設定をそれほど高くせずに)コンパイルしましたか?

また、あなたのコードはゼロに等しいsysWriteBuffer1回呼び出します-多分それは(部分的に)それを説明しますか?readBytes

sysWriteBufferをインライン化することもできます(コンパイラースイッチを介して、または手動で)。

「インライン化」とは、関数を呼び出すオーバーヘッドを取り除くために、関数の本体をその呼び出しサイトにコピーすることを意味します。コンパイラがこれを自動的に行う場合があります(-O3はgccでこの最適化を有効にすると思います)。gccinlineでキーワードを使用して、関数をインライン化するようにコンパイラーに指示することもできます。これを行うと、宣言は次のようになります。

static inline int sysWriteBuffer(int fdout, char *buffer, ssize_t readBytes) {
....
于 2009-04-20T18:44:16.443 に答える
3

mmap(2)を調べてください。

ftell / freadの優れた点を捨てることになりますが、読み取りスループットが本当に重要な場合は、間接化のレイヤーをスキップします。

于 2009-04-20T19:10:10.140 に答える
2

ソースコードを比較せずに言うのは難しいです。猫とGNU猫を比較する場合は、数時間/日経過したコードと20年以上進化したコードを比較していることを忘れないでください。

より包括的なパフォーマンス分析を実行して、異なる入力サイズで、異なるデバイス(RAMディスクが適切)から、連続して複数回、両方のプログラムを実行することをお勧めします。プログラムのどこが遅いかを判断する必要があります。

cat自体は非常に些細なことなので(コメントで、すでにコンパイルを最適化しているとおっしゃっていました)、観察しているパフォーマンスへの影響は実際のアルゴリズムではなく、プログラムのロード時間にあると思います。システムバイナリが事前にリンクされている場合(これは最近のほとんどのディストリビューションで一般的です)、自分でコンパイルするどのプログラムよりも速くロードされることがわかります(プログラムを事前リンクするまで)。

于 2009-04-20T19:24:08.873 に答える
1

いくら?正規の猫は次のようなものです

char bufr[BUFSIZ];
ssize_t len;

while((len=read(fdin, bufr, BUFSIZ)) >0)
     write(fdout, bufr, len);

これにより、いくつかの指示が節約されます。

于 2009-04-20T18:41:33.530 に答える
1

strace両方のを比較しましたか?-ttシステムコールのタイミングを取得するために、パラメータを使用しようとする場合があります。

于 2009-04-20T18:52:03.380 に答える