Explain this Algorithm: 2 for 1 Prioritization Schedule Using Heap (from RakNet)

78 views Asked by At

Imagine we have a network stack that schedules traffic sends at 4 priority levels [0,3]:

  • Generally, two messages at priority 0 are sent for every one message sent at priority 1.
  • Likewise, two messages at priority 1 are sent for every one message sent at priority 2, and so on.
  • Additionally, higher priority messages scheduled earlier are never usurped by lower priority messages scheduled after.
  • But higher priority messages scheduled after may usurp lower priority messages scheduled before.

RakNet has such an algorithm which uses a MIN heap with weights determined by the algorithm below. I would like to better understand the math behind this algorithm.

Simplified/cleaned from RakNet

int NUMBER_OF_PRIORITIES = 4;
int heapWeights[NUMBER_OF_PRIORITIES];

Heap<int, InternalPacket*, false> packetQueue;

void InitHeapWeights(void)
{
    for (int priorityLevel = 0; priorityLevel < NUMBER_OF_PRIORITIES; priorityLevel++)
        heapWeights[priorityLevel] = (1 << priorityLevel) * priorityLevel + priorityLevel;
}

int GetNextWeight(int priorityLevel)
{
    int next = heapWeights[priorityLevel];
    if (packetQueue.Size() > 0)
    {
        int peekPriorityLevel = packetQueue.Peek()->priority;
        int weight = packetQueue.PeekWeight();
        int min = weight - (1 << peekPriorityLevel) * peekPriorityLevel + peekPriorityLevel;
        if (next < min)
            next = min + (1 << priorityLevel) * priorityLevel + priorityLevel;
        heapWeights[priorityLevel] = next + (1 << priorityLevel) * (priorityLevel + 1) + priorityLevel;
    }
    else
    {
        InitHeapWeights();
    }
    return next;
}

What I Understand So Far The algorithm always returns whatever state is in the seed array(int heapWeights[NUMBER_OF_PRIORITIES];), and the value it computes is for the next time the algorithm is called.

State is kept in two places:

  • The seed array, whose values scale upwards as more messages are scheduled at a given priority
  • The packetQueue (min heap): the algorithm uses the priority level of the next-in-line message to compute some sort of minimum weight for the next message at that priority level.

For 4 priority levels, void InitHeapWeights(void) initializes the seed array to [0, 3, 10, 27] and resets when the queue is empty (but not before returning the latest value for a given priority level)

The initial weights (w0) are calculated as: w0 = 2^priorityLevel * priorityLevel + priorityLevel;

Generally, when the weight is updated, we do: w1 = w0 + 2^priorityLevel * (priorityLevel + 1) + priorityLevel

The edge case scenario checks whether w0 is less than the weight of the next-in-line message minus w0 for the next-in-line's priority level. I'm not sure why that is.

0

There are 0 answers