summaryrefslogtreecommitdiff
path: root/main/sched.c
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2014-02-11 20:17:42 +0000
committerJoshua Colp <jcolp@digium.com>2014-02-11 20:17:42 +0000
commit6bdf2c4eab6524f85fa2245b9d796f5f4c46911a (patch)
tree492f989fbdb4c7aec1c6610b82fdcd69d426bea5 /main/sched.c
parent0ebbeac69fb8a407ea8d5e434efefb12e80fb596 (diff)
scheduler: Remove hashtab usage.
This is a first stab at tweaking the performance profile of the scheduler. Removing the hashtab usage removes an extra memory allocation when scheduling something and makes it so rescheduling does not incur any memory allocation at all. Review: https://reviewboard.asterisk.org/r/3199/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407958 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/sched.c')
-rw-r--r--main/sched.c103
1 files changed, 41 insertions, 62 deletions
diff --git a/main/sched.c b/main/sched.c
index fa809e172..4de021432 100644
--- a/main/sched.c
+++ b/main/sched.c
@@ -47,9 +47,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/channel.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/dlinkedlists.h"
-#include "asterisk/hashtab.h"
#include "asterisk/heap.h"
#include "asterisk/threadstorage.h"
@@ -85,9 +82,7 @@ struct sched_thread {
struct ast_sched_context {
ast_mutex_t lock;
unsigned int eventcnt; /*!< Number of events processed */
- unsigned int schedcnt; /*!< Number of outstanding schedule events */
unsigned int highwater; /*!< highest count so far */
- struct ast_hashtab *schedq_ht; /*!< hash table for fast searching */
struct ast_heap *sched_heap;
struct sched_thread *sched_thread;
@@ -188,20 +183,6 @@ int ast_sched_start_thread(struct ast_sched_context *con)
return 0;
}
-static int sched_cmp(const void *a, const void *b)
-{
- const struct sched *as = a;
- const struct sched *bs = b;
- return as->id != bs->id; /* return 0 on a match like strcmp would */
-}
-
-static unsigned int sched_hash(const void *obj)
-{
- const struct sched *s = obj;
- unsigned int h = s->id;
- return h;
-}
-
static int sched_time_cmp(void *a, void *b)
{
return ast_tvcmp(((struct sched *) b)->when, ((struct sched *) a)->when);
@@ -218,8 +199,6 @@ struct ast_sched_context *ast_sched_context_create(void)
ast_mutex_init(&tmp->lock);
tmp->eventcnt = 1;
- tmp->schedq_ht = ast_hashtab_create(23, sched_cmp, ast_hashtab_resize_java, ast_hashtab_newsize_java, sched_hash, 1);
-
if (!(tmp->sched_heap = ast_heap_create(8, sched_time_cmp,
offsetof(struct sched, __heap_index)))) {
ast_sched_context_destroy(tmp);
@@ -252,9 +231,6 @@ void ast_sched_context_destroy(struct ast_sched_context *con)
con->sched_heap = NULL;
}
- ast_hashtab_destroy(con->schedq_ht, NULL);
- con->schedq_ht = NULL;
-
ast_mutex_unlock(&con->lock);
ast_mutex_destroy(&con->lock);
@@ -330,14 +306,8 @@ static void schedule(struct ast_sched_context *con, struct sched *s)
{
ast_heap_push(con->sched_heap, s);
- if (!ast_hashtab_insert_safe(con->schedq_ht, s)) {
- ast_log(LOG_WARNING,"Schedule Queue entry %d is already in table!\n", s->id);
- }
-
- con->schedcnt++;
-
- if (con->schedcnt > con->highwater) {
- con->highwater = con->schedcnt;
+ if (ast_heap_size(con->sched_heap) > con->highwater) {
+ con->highwater = ast_heap_size(con->sched_heap);
}
}
@@ -419,16 +389,40 @@ int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback
return ast_sched_add_variable(con, when, callback, data, 0);
}
-const void *ast_sched_find_data(struct ast_sched_context *con, int id)
+static struct sched *sched_find(struct ast_sched_context *con, int id)
{
- struct sched tmp,*res;
- tmp.id = id;
- res = ast_hashtab_lookup(con->schedq_ht, &tmp);
- if (res)
- return res->data;
+ int x;
+ size_t heap_size;
+
+ heap_size = ast_heap_size(con->sched_heap);
+ for (x = 1; x <= heap_size; x++) {
+ struct sched *cur = ast_heap_peek(con->sched_heap, x);
+
+ if (cur->id == id) {
+ return cur;
+ }
+ }
+
return NULL;
}
+const void *ast_sched_find_data(struct ast_sched_context *con, int id)
+{
+ struct sched *s;
+ const void *data = NULL;
+
+ ast_mutex_lock(&con->lock);
+
+ s = sched_find(con, id);
+ if (s) {
+ data = s->data;
+ }
+
+ ast_mutex_unlock(&con->lock);
+
+ return data;
+}
+
/*! \brief
* Delete the schedule entry with number
* "id". It's nearly impossible that there
@@ -441,9 +435,7 @@ int ast_sched_del(struct ast_sched_context *con, int id)
int _ast_sched_del(struct ast_sched_context *con, int id, const char *file, int line, const char *function)
#endif
{
- struct sched *s, tmp = {
- .id = id,
- };
+ struct sched *s = NULL;
int *last_id = ast_threadstorage_get(&last_del_id, sizeof(int));
DEBUG(ast_debug(1, "ast_sched_del(%d)\n", id));
@@ -453,18 +445,13 @@ int _ast_sched_del(struct ast_sched_context *con, int id, const char *file, int
}
ast_mutex_lock(&con->lock);
- s = ast_hashtab_lookup(con->schedq_ht, &tmp);
+
+ s = sched_find(con, id);
if (s) {
if (!ast_heap_remove(con->sched_heap, s)) {
ast_log(LOG_WARNING,"sched entry %d not in the sched heap?\n", s->id);
}
- if (!ast_hashtab_remove_this_object(con->schedq_ht, s)) {
- ast_log(LOG_WARNING,"Found sched entry %d, then couldn't remove it?\n", s->id);
- }
-
- con->schedcnt--;
-
sched_release(con, s);
}
@@ -506,7 +493,7 @@ void ast_sched_report(struct ast_sched_context *con, struct ast_str **buf, struc
size_t heap_size;
memset(countlist, 0, sizeof(countlist));
- ast_str_set(buf, 0, " Highwater = %d\n schedcnt = %d\n", con->highwater, con->schedcnt);
+ ast_str_set(buf, 0, " Highwater = %d\n schedcnt = %zd\n", con->highwater, ast_heap_size(con->sched_heap));
ast_mutex_lock(&con->lock);
@@ -543,9 +530,9 @@ void ast_sched_dump(struct ast_sched_context *con)
int x;
size_t heap_size;
#ifdef SCHED_MAX_CACHE
- ast_debug(1, "Asterisk Schedule Dump (%d in Q, %d Total, %d Cache, %d high-water)\n", con->schedcnt, con->eventcnt - 1, con->schedccnt, con->highwater);
+ ast_debug(1, "Asterisk Schedule Dump (%zd in Q, %d Total, %d Cache, %d high-water)\n", ast_heap_size(con->sched_heap), con->eventcnt - 1, con->schedccnt, con->highwater);
#else
- ast_debug(1, "Asterisk Schedule Dump (%d in Q, %d Total, %d high-water)\n", con->schedcnt, con->eventcnt - 1, con->highwater);
+ ast_debug(1, "Asterisk Schedule Dump (%zd in Q, %d Total, %d high-water)\n", ast_heap_size(con->sched_heap), con->eventcnt - 1, con->highwater);
#endif
ast_debug(1, "=============================================================\n");
@@ -595,12 +582,6 @@ int ast_sched_runq(struct ast_sched_context *con)
current = ast_heap_pop(con->sched_heap);
- if (!ast_hashtab_remove_this_object(con->schedq_ht, current)) {
- ast_log(LOG_ERROR,"Sched entry %d was in the schedq list but not in the hashtab???\n", current->id);
- }
-
- con->schedcnt--;
-
/*
* At this point, the schedule queue is still intact. We
* have removed the first event and the rest is still there,
@@ -637,20 +618,18 @@ int ast_sched_runq(struct ast_sched_context *con)
long ast_sched_when(struct ast_sched_context *con,int id)
{
- struct sched *s, tmp;
+ struct sched *s;
long secs = -1;
DEBUG(ast_debug(1, "ast_sched_when()\n"));
ast_mutex_lock(&con->lock);
- /* these next 2 lines replace a lookup loop */
- tmp.id = id;
- s = ast_hashtab_lookup(con->schedq_ht, &tmp);
-
+ s = sched_find(con, id);
if (s) {
struct timeval now = ast_tvnow();
secs = s->when.tv_sec - now.tv_sec;
}
+
ast_mutex_unlock(&con->lock);
return secs;