8

キューのような固定サイズのデータ​​構造を格納する循環バッファーを実装していました。この循環バッファーは、3 つのパラメーターで初期化されます。

/*
 * Initialize the ring buffer.
 * @capacity Max capacity of ring buffer.
 * @item_size Fixed size of item that will be put in this circular buffer.
 * @item_cleaner Clean callback, NULL if cleanup not required.
 */
ringbuf*
ringbuf_create(size_t capacity, size_t item_size, clean_up_cb item_cleaner)

私の循環バッファは常にwrappingモードになっています。つまり、新しいアイテムが完全な循環バッファに置かれると、最後のアイテムが常に置き換えられます。動的に割り当てられたオブジェクトもこのバッファーに入れることができるため、循環バッファーはクリーンアップ コールバック関数を参照し続け、アイテムが置換または削除されたときにアイテムを解放します。しかし同時に、このコールバック関数はNULL(クリーンアップが不要な場合) も可能です。私のコードのいたるところに、次のようなステートメントがあります:-

if(buffer->callback != NULL)
   buffer->callback(item);

さて、これらのifステートメントを防ぐために、ユーザーがコールバック関数を提供しない場合、空のスタブ関数を配置します。これにより、コールバック関数が存在するかどうかを毎回確認することができなくなりNULLます。

このアプローチを使用すると、私のコードはきれいに見えます。でもよくわからないんですけど、どっちが速いですか?アセンブリ レベルでは、速度に関してとはどのようempty function callに関連していますか? if statementそれらは同等ですか?

4

2 に答える 2

5

速度を気にせずに、おそらくコーディングするだけです。

 if (buffer->callback) buffer->callback(item);

それがそのまま明確で慣用的であるという理由だけで。そして、それは確かにnull関数呼び出しよりも遅くなることはありません。

于 2012-05-29T10:53:00.040 に答える
4

空のスタブ関数は、実際には 2 つの JMP 操作と、CPU 上の PUSH/POP 操作の割り当てです。IF は通常、JMP+PUSHS+POPS よりもはるかに安価な単一の COMP 操作です。

IF が通常 false/true を返す場合、IF が「予測可能」である限り (通常は true または false を返すか、何らかのパターンがある場合)、結果を予測することにより、CPU が非常に良い方法で IF を最適化するので、私はそれについて心配しません。真/偽)

私はIFと一緒に行きます。

于 2012-05-29T11:02:40.717 に答える