4

Libevは、3つのデータ構造を使用して、さまざまなウォッチャーを格納します。

ヒープ:ev_timerやなどの時間でソートされたウォッチャー用ev_periodic

リンクリスト:ev_io、、などev_signalev_child

配列ev_prepare、、などev_checkev_async

ヒープを使用してタイマーウォッチャーを格納することは間違いありません。しかし、リンクリストと配列を選択する基準は何ですか?

ev_ioウォッチャーを格納するデータ構造は少し複雑に見えます。これは最初にfd、インデックスとしての配列であり、配列内の要素はのリンクリストですev_io watcher。リンクリストを要素として使用する場合は、配列にスペースを割り当てる方が便利です。それが理由ですか?

または、の挿入または削除操作ev_ioがより頻繁で、ev_prepareより安定しているように見えるという理由だけで?

または他の理由はありますか?

4

2 に答える 2

5

同じfd(シグナルの場合も同様)のioウォッチャーは少数(通常は1人、ほとんどの場合は最大2人)であることが期待されます。リストリンクをウォッチャーに配置することは、ウォッチャーごとに配列が使用された場合に必要となるような、追加の割り当てが必要ないことを意味します。多くのI/Oウォッチャーが同じfdでアクティブだった場合、このリンクリストアプローチは遅くなります。

挿入と削除が非常に高速であるため、配列が使用されます(ウォッチャーは配列インデックスを格納します)。4バイトのインデックスを使用すると、64ビットマシンのメモリ要件も削減され(たとえば、二重リンクリストの場合は16バイトであるのに対し、ウォッチャーごとに12バイト)、ポインターの配列を使用すると、すべてのポインターがメモリ内で互いに近くになります。一部のウォッチャーにとって頻繁な操作であるスキャン時のキャッシュ効率が向上します。

キャッシュ効率は、2ヒープよりも4ヒープが使用される理由でもあり、ヒープ操作でウォッチャーメモリにアクセスする必要がないように、時間値がヒープデータ構造にコピーされる理由でもあります。

子ウォッチャーは実際には固定サイズのハッシュテーブルを使用します。また、ハッシュバケットあたりの子ウォッチャーの数が少ないことが予想されるため、リストポインターはウォッチャーデータ構造の一部になります。

于 2013-01-07T15:18:54.767 に答える
2

おそらくその理由は、典型的なシナリオではev_ioをfdで検索する必要があるためです。基礎となるライブラリ(epoll、selectなど)は、何らかのイベントを持つfdを提供します。Libevはそれをインデックスとして使用し、呼び出す必要のあるイベントウォッチャーのリンクリストを繰り返し処理します。そのため、イベントの発生が速くなる可能性があります。

于 2012-12-07T21:17:59.667 に答える