Skip to content
This repository was archived by the owner on Jul 16, 2019. It is now read-only.

Commit 5ed80e6

Browse files
Merge pull request #1 from bmerry/easy-optimisations
Optimisations for common cases
2 parents 3944c9f + 903f671 commit 5ed80e6

File tree

3 files changed

+41
-21
lines changed

3 files changed

+41
-21
lines changed

src/_spead/include/spead_packet.h

+2
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ typedef struct {
137137
int is_valid;
138138
int64_t heap_cnt;
139139
int64_t heap_len;
140+
// Total bytes of payload received (possibly including duplicated packets)
141+
int64_t received_len;
140142
int has_all_packets;
141143
SpeadPacket *head_pkt;
142144
SpeadPacket *last_pkt;

src/_spead/spead_packet.cpp

+36-19
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <string.h>
12
#include "include/spead_packet.h"
23

34
// Return data at the specified offset (in bits) and # of bits as
@@ -175,6 +176,7 @@ void spead_heap_init(SpeadHeap *heap) {
175176
heap->is_valid = 0;
176177
heap->heap_cnt = SPEAD_ERR;
177178
heap->heap_len = SPEAD_ERR;
179+
heap->received_len = 0;
178180
heap->has_all_packets = SPEAD_ERR;
179181
heap->head_pkt = NULL;
180182
heap->last_pkt = NULL;
@@ -213,22 +215,29 @@ int spead_heap_add_packet(SpeadHeap *heap, SpeadPacket *pkt) {
213215
}
214216
else { // We need to insert this packet in the correct order
215217
if (heap->heap_cnt != pkt->heap_cnt) return SPEAD_ERR;
216-
_pkt = heap->head_pkt;
217-
// Find the right slot to insert this pkt
218-
if (pkt->payload_off < _pkt->payload_off) {
219-
pkt->next = heap->head_pkt;
220-
heap->head_pkt = pkt;
218+
if (pkt->payload_off >= heap->last_pkt->payload_off) {
219+
// Fast path: in-order packet gets added to the tail
220+
heap->last_pkt->next = pkt;
221+
heap->last_pkt = pkt;
221222
} else {
222-
while (_pkt->next != NULL && _pkt->next->payload_off < pkt->payload_off) {
223-
_pkt = _pkt->next;
224-
}
225-
// Insert the pkt
226-
pkt->next = _pkt->next;
227-
_pkt->next = pkt;
228-
if (pkt->next == NULL) heap->last_pkt = pkt;
229-
} // else if packet does not belong at head
223+
_pkt = heap->head_pkt;
224+
// Find the right slot to insert this pkt
225+
if (pkt->payload_off < _pkt->payload_off) {
226+
pkt->next = heap->head_pkt;
227+
heap->head_pkt = pkt;
228+
} else {
229+
while (_pkt->next != NULL && _pkt->next->payload_off < pkt->payload_off) {
230+
_pkt = _pkt->next;
231+
}
232+
// Insert the pkt
233+
pkt->next = _pkt->next;
234+
_pkt->next = pkt;
235+
if (pkt->next == NULL) heap->last_pkt = pkt;
236+
} // else if packet does not belong at head
237+
}
230238
}
231239
if (pkt->heap_len != SPEAD_ERR) heap->heap_len = pkt->heap_len;
240+
heap->received_len += pkt->payload_len;
232241
heap->has_all_packets = SPEAD_ERR;
233242
return spead_heap_got_all_packets(heap);
234243
}
@@ -238,6 +247,10 @@ int spead_heap_got_all_packets(SpeadHeap *heap) {
238247
if (heap->heap_len == SPEAD_ERR || pkt == NULL) return 0; // Don't compute if we can't know the answer
239248
if (heap->has_all_packets != SPEAD_ERR) return heap->has_all_packets; // Don't recompute if we do know the answer
240249
heap->has_all_packets = 0;
250+
// If we haven't received as much payload as we're expecting, we're not
251+
// done. If we have, we still need to check the actual packets because
252+
// there might be duplicates.
253+
if (heap->received_len < heap->heap_len) return 0;
241254
while (pkt->next != NULL) {
242255
if (pkt->payload_off + pkt->payload_len != pkt->next->payload_off) return 0;
243256
pkt = pkt->next;
@@ -313,20 +326,24 @@ int spead_heap_finalize(SpeadHeap *heap) {
313326
if (item->val == NULL) return SPEAD_ERR;
314327
// Dig through the payloads to retrieve item value
315328
pkt2 = heap->head_pkt;
316-
for (o=0; o < item->len; o++) {
329+
o = 0;
330+
while (o < item->len) {
317331
while (pkt2 != NULL && (pkt2->payload_off + pkt2->payload_len <= off + o)) {
318332
pkt2 = pkt2->next;
319333
}
320334
// If packet with relevant data is missing, fill with zeros and mark invalid
321335
if (pkt2 == NULL || pkt2->payload_off > off + o) {
322336
//printf("Copying value[%d] = 00 (missing)\n", o);
323-
item->val[o] = '\x00';
337+
int64_t end = (pkt2 == NULL) ? item->len : pkt2->payload_off - off;
338+
memset(&item->val[o], 0, end - o);
324339
item->is_valid = 0;
340+
o = end;
325341
} else {
326-
item->val[o] = pkt2->payload[off + o - pkt2->payload_off];
327-
//printf("o=%d, off=%d, payload_off=%d, index=%d\n",
328-
// o, off, pkt2->payload->offset, off + o - pkt2->payload->offset);
329-
//printf("Copying value[%d] = %02x\n", o, (uint8_t)item->val[o]);
342+
int64_t end = pkt2->payload_off + pkt2->payload_len - off;
343+
if (item->len < end)
344+
end = item->len;
345+
memcpy(&item->val[o], &pkt2->payload[off + o - pkt2->payload_off], end - o);
346+
o = end;
330347
}
331348
}
332349
}

src/spead.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import numpy
1212
import logging
1313
import time
14+
from collections import deque
1415
from numpy.lib.utils import safe_eval
1516
import _spead
1617

@@ -776,9 +777,9 @@ def write(self, data):
776777
class TransportUDPrx(_spead.BufferSocket):
777778
def __init__(self, port, pkt_count=128, buffer_size=0):
778779
_spead.BufferSocket.__init__(self, pkt_count)
779-
self.pkts = []
780+
self.pkts = deque()
780781
def callback(pkt):
781-
self.pkts.insert(0, pkt)
782+
self.pkts.appendleft(pkt)
782783
self.set_callback(callback)
783784
self.start(port, buffer_size)
784785

0 commit comments

Comments
 (0)