The analysis engine manages its own buffers to prevent fragmentation and improve performance. A single block of memory is allocated and made unswappable. It is then divided into multiple 1M segments, which are divided into 8K pools. Each pool contains the same size buffer. The buffer sizes range from 64 bytes to 64K bytes. Therefore, some buffers are made of multiple pools. For each pool size there are three available queues, a full queue, and a free queue. When a request is made for a buffer, the smallest buffer size that will fulfill the request is determined. Then the lock for one of the available queues of that pool is requested. If it is unavailable, control is returned immediately, and the lock of the next available queue is requested. This repeats until a queue is available. Freeing a buffer requires a wait for the lock of the pool's queue. When it is obtained, a bit flag is cleared and the counter decremented to free the buffer. The Manager periodically checks the available queues for all buffer sizes and removes pools that have no available buffers. These are requeued to the full queue. It checks the full queue for pools that have available buffers and requeues those to the free queue. When the Manager checks the free queue, it requeues pools that have some unavailable buffers to one of the available queues, attempting to equalize the number of pools in each of the three queues. However, if there are pools in which all buffers are available, they are requeued to a general list which can be used to fulfill requests for buffers of a different size. |