]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-7501: improve linked list algorithm in a few places to help performance
authorAnthony Minessale <anthm@freeswitch.org>
Tue, 7 Apr 2015 20:39:04 +0000 (15:39 -0500)
committerMichael Jerris <mike@jerris.com>
Thu, 28 May 2015 17:47:17 +0000 (12:47 -0500)
src/include/switch_vidderbuffer.h
src/switch_rtp.c
src/switch_utils.c
src/switch_vidderbuffer.c

index 6f2b02e7a534bdf6c783ff40b7369c075930ddcf..d59ad3c46ba7ede04467fcfcc1b8c9d7f9986be5 100644 (file)
@@ -45,6 +45,7 @@ SWITCH_DECLARE(void) switch_vb_reset(switch_vb_t *vb);
 SWITCH_DECLARE(void) switch_vb_debug_level(switch_vb_t *vb, uint8_t level);
 SWITCH_DECLARE(int) switch_vb_frame_count(switch_vb_t *vb);
 SWITCH_DECLARE(int) switch_vb_poll(switch_vb_t *vb);
+SWITCH_DECLARE(switch_status_t) switch_vb_push_packet(switch_vb_t *vb, switch_rtp_packet_t *packet, switch_size_t len);
 SWITCH_DECLARE(switch_status_t) switch_vb_put_packet(switch_vb_t *vb, switch_rtp_packet_t *packet, switch_size_t len);
 SWITCH_DECLARE(switch_status_t) switch_vb_get_packet(switch_vb_t *vb, switch_rtp_packet_t *packet, switch_size_t *len);
 SWITCH_DECLARE(uint32_t) switch_vb_pop_nack(switch_vb_t *vb);
index 06670b90bf76ebebcb701b470b6952cbb808ae03..a615b1449b5311acfb55c24da7ee14508d52660c 100644 (file)
@@ -7018,11 +7018,10 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
                
                if (rtp_session->flags[SWITCH_RTP_FLAG_NACK]) {
                        if (!rtp_session->vbw) {
-                               switch_vb_create(&rtp_session->vbw, 500, 500, rtp_session->pool);
-                               switch_vb_set_flag(rtp_session->vbw, SVB_QUEUE_ONLY);
+                               switch_vb_create(&rtp_session->vbw, 150, 150, rtp_session->pool);
                                //switch_vb_debug_level(rtp_session->vbw, 10);
                        }
-                       switch_vb_put_packet(rtp_session->vbw, (switch_rtp_packet_t *)send_msg, bytes);
+                       switch_vb_push_packet(rtp_session->vbw, (switch_rtp_packet_t *)send_msg, bytes);
                }
 
 #ifdef RTP_WRITE_PLOSS
index d270081b20dd0d75ff025c61fda9d0f6a6176e2c..e53c66d079baa78c49d4edd2e06ae8c6e0854dcb 100644 (file)
@@ -96,6 +96,7 @@ SWITCH_DECLARE(switch_status_t) switch_frame_alloc(switch_frame_t **frame, switc
 typedef struct switch_frame_node_s {
        switch_frame_t *frame;
        int inuse;
+       struct switch_frame_node_s *prev;
        struct switch_frame_node_s *next;
 } switch_frame_node_t;
 
@@ -103,19 +104,37 @@ struct switch_frame_buffer_s {
        switch_frame_node_t *head;
        switch_memory_pool_t *pool;
        switch_mutex_t *mutex;
+       uint32_t total;
 };
 
 static switch_frame_t *find_free_frame(switch_frame_buffer_t *fb, switch_frame_t *orig)
 {
        switch_frame_node_t *np;
+       int x = 0;
 
        switch_mutex_lock(fb->mutex);
+
        for (np = fb->head; np; np = np->next) {
+               x++;
+               
                if (!np->inuse && ((orig->packet && np->frame->packet) || (!orig->packet && !np->frame->packet))) {
+
+                       if (np == fb->head) {
+                               fb->head = np->next;
+                       } else if (np->prev) {
+                               np->prev->next = np->next;
+                       }
+
+                       if (np->next) {
+                               np->next->prev = np->prev;
+                       }
+
+                       fb->total--;
+                       np->prev = np->next = NULL;
                        break;
-               }
+               }               
        }
-
+       
        if (!np) {
                np = switch_core_alloc(fb->pool, sizeof(*np));
                np->frame = switch_core_alloc(fb->pool, sizeof(*np->frame));
@@ -126,11 +145,8 @@ static switch_frame_t *find_free_frame(switch_frame_buffer_t *fb, switch_frame_t
                        np->frame->data = switch_core_alloc(fb->pool, SWITCH_RTP_MAX_BUF_LEN);
                        np->frame->buflen = SWITCH_RTP_MAX_BUF_LEN;
                }
-               np->next = fb->head;
-               fb->head = np;
        }
 
-
        np->frame->samples = orig->samples;
        np->frame->rate = orig->rate;
        np->frame->channels = orig->channels;
@@ -177,10 +193,24 @@ SWITCH_DECLARE(switch_status_t) switch_frame_buffer_free(switch_frame_buffer_t *
 
        old_frame = *frameP;
        *frameP = NULL;
-
+       
        node = (switch_frame_node_t *) old_frame->extra_data;
        node->inuse = 0;
        switch_img_free(&node->frame->img);
+       
+       fb->total++;
+
+       if (fb->head) {
+               fb->head->prev = node;
+       }
+
+       node->next = fb->head;
+       node->prev = NULL;
+       fb->head = node;
+
+       switch_assert(node->next != node);
+       switch_assert(node->prev != node);
+       
 
        switch_mutex_unlock(fb->mutex);
 
index 1cce952e4e53095b8350ac91c33ad389abc6b9ad..1b0c1b7e4d22eaa5fbef392118685d5801c0c0bb 100644 (file)
@@ -44,6 +44,7 @@ typedef struct switch_vb_node_s {
        switch_rtp_packet_t packet;
        uint32_t len;
        uint8_t visible;
+       struct switch_vb_node_s *prev;
        struct switch_vb_node_s *next;
 } switch_vb_node_t;
 
@@ -67,6 +68,7 @@ struct switch_vb_s {
        switch_inthash_t *missing_seq_hash;
        switch_inthash_t *node_hash;
        switch_mutex_t *mutex;
+       switch_mutex_t *list_mutex;
        switch_memory_pool_t *pool;
        int free_pool;
        switch_vb_flag_t flags;
@@ -74,25 +76,26 @@ struct switch_vb_s {
 
 static inline switch_vb_node_t *new_node(switch_vb_t *vb)
 {
-       switch_vb_node_t *np, *last = NULL;
+       switch_vb_node_t *np;
+
+       switch_mutex_lock(vb->list_mutex);
 
        for (np = vb->node_list; np; np = np->next) {
                if (!np->visible) {
                        break;
                }
-               last = np;
        }
 
        if (!np) {
                
                np = switch_core_alloc(vb->pool, sizeof(*np));
-       
-               if (last) {
-                       last->next = np;
-               } else {
-                       vb->node_list = np;
+               
+               np->next = vb->node_list;
+               if (np->next) {
+                       np->next->prev = np;
                }
-
+               vb->node_list = np;
+               
        }
 
        switch_assert(np);
@@ -101,41 +104,89 @@ static inline switch_vb_node_t *new_node(switch_vb_t *vb)
        vb->visible_nodes++;
        np->parent = vb;
 
+       switch_mutex_unlock(vb->list_mutex);
+
        return np;
 }
 
-#if 0
-static inline switch_vb_node_t *find_seq(switch_vb_t *vb, uint16_t seq)
+static inline void push_to_top(switch_vb_t *vb, switch_vb_node_t *node)
 {
-       switch_vb_node_t *np;
-       for (np = vb->node_list; np; np = np->next) {
-               if (!np->visible) continue;
+       if (node == vb->node_list) {
+               vb->node_list = node->next;
+       } else if (node->prev) {
+               node->prev->next = node->next;
+       }
                        
-               if (ntohs(np->packet.header.seq) == ntohs(seq)) {
-                       return np;
-               }
+       if (node->next) {
+               node->next->prev = node->prev;
        }
 
-       return NULL;
+       node->next = vb->node_list;
+       node->prev = NULL;
+
+       if (node->next) {
+               node->next->prev = node;
+       }
+
+       vb->node_list = node;
+
+       switch_assert(node->next != node);
+       switch_assert(node->prev != node);
 }
-#endif
 
-static inline void hide_node(switch_vb_node_t *node)
+static inline void hide_node(switch_vb_node_t *node, switch_bool_t pop)
 {
+       switch_vb_t *vb = node->parent;
+
+       switch_mutex_lock(vb->list_mutex);
+
        if (node->visible) {
                node->visible = 0;
-               node->parent->visible_nodes--;
+               vb->visible_nodes--;
+
+               if (pop) {
+                       push_to_top(vb, node);
+               }
+       }
+
+       switch_core_inthash_delete(vb->node_hash, node->packet.header.seq);
+
+       switch_mutex_unlock(vb->list_mutex);
+}
+
+static inline void sort_free_nodes(switch_vb_t *vb)
+{
+       switch_vb_node_t *np, *this_np;
+       int start = 0;
+
+       switch_mutex_lock(vb->list_mutex);
+       np = vb->node_list;
+
+       while(np) {
+               this_np = np;
+               np = np->next;
+
+               if (this_np->visible) {
+                       start++;
+               }
+
+               if (start && !this_np->visible) {
+                       push_to_top(vb, this_np);
+               }               
        }
-       switch_core_inthash_delete(node->parent->node_hash, node->packet.header.seq);
+
+       switch_mutex_unlock(vb->list_mutex);
 }
 
 static inline void hide_nodes(switch_vb_t *vb)
 {
        switch_vb_node_t *np;
 
+       switch_mutex_lock(vb->list_mutex);
        for (np = vb->node_list; np; np = np->next) {
-               hide_node(np);
+               hide_node(np, SWITCH_FALSE);
        }
+       switch_mutex_unlock(vb->list_mutex);
 }
 
 static inline void drop_ts(switch_vb_t *vb, uint32_t ts)
@@ -143,15 +194,22 @@ static inline void drop_ts(switch_vb_t *vb, uint32_t ts)
        switch_vb_node_t *np;
        int x = 0;
 
+       switch_mutex_lock(vb->list_mutex);
        for (np = vb->node_list; np; np = np->next) {
                if (!np->visible) continue;
 
                if (ts == np->packet.header.ts) {
-                       hide_node(np);
+                       hide_node(np, SWITCH_FALSE);
                        x++;
                }
        }
 
+       if (x) {
+               sort_free_nodes(vb);
+       }
+
+       switch_mutex_unlock(vb->list_mutex);
+       
        if (x) vb->complete_frames--;
 }
 
@@ -159,6 +217,7 @@ static inline uint32_t vb_find_lowest_ts(switch_vb_t *vb)
 {
        switch_vb_node_t *np, *lowest = NULL;
        
+       switch_mutex_lock(vb->list_mutex);
        for (np = vb->node_list; np; np = np->next) {
                if (!np->visible) continue;
 
@@ -166,6 +225,7 @@ static inline uint32_t vb_find_lowest_ts(switch_vb_t *vb)
                        lowest = np;
                }
        }
+       switch_mutex_unlock(vb->list_mutex);
 
        return lowest ? lowest->packet.header.ts : 0;
 }
@@ -239,6 +299,7 @@ static inline switch_vb_node_t *vb_find_lowest_seq(switch_vb_t *vb)
 {
        switch_vb_node_t *np, *lowest = NULL;
        
+       switch_mutex_lock(vb->list_mutex);
        for (np = vb->node_list; np; np = np->next) {
                if (!np->visible) continue;
 
@@ -246,6 +307,7 @@ static inline switch_vb_node_t *vb_find_lowest_seq(switch_vb_t *vb)
                        lowest = np;
                }
        }
+       switch_mutex_unlock(vb->list_mutex);
 
        return lowest;
 }
@@ -294,7 +356,9 @@ static inline switch_status_t vb_next_packet(switch_vb_t *vb, switch_vb_node_t *
 
 static inline void free_nodes(switch_vb_t *vb)
 {
+       switch_mutex_lock(vb->list_mutex);
        vb->node_list = NULL;
+       switch_mutex_unlock(vb->list_mutex);
 }
 
 SWITCH_DECLARE(void) switch_vb_set_flag(switch_vb_t *vb, switch_vb_flag_t flag)
@@ -370,7 +434,7 @@ SWITCH_DECLARE(switch_status_t) switch_vb_create(switch_vb_t **vbp, uint32_t min
        switch_core_inthash_init(&vb->missing_seq_hash);
        switch_core_inthash_init(&vb->node_hash);
        switch_mutex_init(&vb->mutex, SWITCH_MUTEX_NESTED, pool);
-
+       switch_mutex_init(&vb->list_mutex, SWITCH_MUTEX_NESTED, pool);
 
        *vbp = vb;
 
@@ -569,7 +633,7 @@ SWITCH_DECLARE(switch_status_t) switch_vb_get_packet(switch_vb_t *vb, switch_rtp
                *packet = node->packet;
                *len = node->len;
                memcpy(packet->body, node->packet.body, node->len);
-               hide_node(node);
+               hide_node(node, SWITCH_TRUE);
 
                vb_debug(vb, 1, "GET packet ts:%u seq:%u %s\n", ntohl(packet->header.ts), ntohs(packet->header.seq), packet->header.m ? " <MARK>" : "");