It is expected that there are only a few (usually one and almost always no more than two) io observers for the same fd (similarly for signals). Placing the list links in the observer means that no additional allocation is required, as would be necessary if the array were used for each observer. If many I / O watchers were active on the same fd, this linked list approach would be slower.
Arrays are used because insertion and deletion are very fast (the observer stores the index of the array). Using a 4-byte index also reduces memory requirements on 64-bit machines (12 bytes per observer, unlike, for example, 16 for a doubly linked list), and using an array of pointers means that all pointers are next to each other in memory , which increases the efficiency of caching during scanning, which is a frequent action for some observers.
Cache efficiency is also the reason that the 4-heap is used in the 2-heap and the reason that time values ββare copied to the heap data structure in order to avoid the need for access to the observer's memory when working with the heap.
Child observers actually use a hash table of a fixed size, and again the expectation is that the number of observers for the hash bucket is small, so list pointers become part of the observer data structure.
source share