]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Rate limit calls to fsync() to 1 per second after astdb updates.
authorRussell Bryant <russell@russellbryant.com>
Fri, 10 Sep 2010 20:31:58 +0000 (20:31 +0000)
committerRussell Bryant <russell@russellbryant.com>
Fri, 10 Sep 2010 20:31:58 +0000 (20:31 +0000)
Astdb was determined to be one of the most significant bottlenecks in SIP
registration processing.  This patch improved the speed of an astdb load
test by 50000% (yes, Fifty-Thousand Percent).  On this particular load test
setup, this doubled the number of SIP registrations the server could handle.

Review: https://reviewboard.asterisk.org/r/825/

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@286112 65c4cc65-6c06-0410-ace0-fbb531ad65f3

main/db.c

index 9129b321c44ab533f636cd437f38eda38ebafd23..ce8a9069c1aff36ed8b451a76629edd846567ec5 100644 (file)
--- a/main/db.c
+++ b/main/db.c
@@ -102,6 +102,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 static DB *astdb;
 AST_MUTEX_DEFINE_STATIC(dblock);
+static ast_cond_t dbcond;
+
+static void db_sync(void);
 
 static int dbinit(void) 
 {
@@ -182,7 +185,7 @@ int ast_db_deltree(const char *family, const char *keytree)
                        counter++;
                }
        }
-       astdb->sync(astdb, 0);
+       db_sync();
        ast_mutex_unlock(&dblock);
        return counter;
 }
@@ -207,7 +210,7 @@ int ast_db_put(const char *family, const char *keys, const char *value)
        data.data = (char *) value;
        data.size = strlen(value) + 1;
        res = astdb->put(astdb, &key, &data, 0);
-       astdb->sync(astdb, 0);
+       db_sync();
        ast_mutex_unlock(&dblock);
        if (res)
                ast_log(LOG_WARNING, "Unable to put value '%s' for key '%s' in family '%s'\n", value, keys, family);
@@ -276,7 +279,7 @@ int ast_db_del(const char *family, const char *keys)
        key.size = fullkeylen + 1;
        
        res = astdb->del(astdb, &key, 0);
-       astdb->sync(astdb, 0);
+       db_sync();
        
        ast_mutex_unlock(&dblock);
 
@@ -718,8 +721,50 @@ static int manager_dbdeltree(struct mansession *s, const struct message *m)
        return 0;
 }
 
+/*!
+ * \internal
+ * \brief Signal the astdb sync thread to do its thing.
+ *
+ * \note dblock is assumed to be held when calling this function.
+ */
+static void db_sync(void)
+{
+       ast_cond_signal(&dbcond);
+}
+
+/*!
+ * \internal
+ * \brief astdb sync thread
+ *
+ * This thread is in charge of syncing astdb to disk after a change.
+ * By pushing it off to this thread to take care of, this I/O bound operation
+ * will not block other threads from performing other critical processing.
+ * If changes happen rapidly, this thread will also ensure that the sync
+ * operations are rate limited.
+ */
+static void *db_sync_thread(void *data)
+{
+       ast_mutex_lock(&dblock);
+       for (;;) {
+               ast_cond_wait(&dbcond, &dblock);
+               ast_mutex_unlock(&dblock);
+               sleep(1);
+               ast_mutex_lock(&dblock);
+               astdb->sync(astdb, 0);
+       }
+
+       return NULL;
+}
+
 int astdb_init(void)
 {
+       pthread_t dont_care;
+
+       ast_cond_init(&dbcond, NULL);
+       if (ast_pthread_create_background(&dont_care, NULL, db_sync_thread, NULL)) {
+               return -1;
+       }
+
        dbinit();
        ast_cli_register_multiple(cli_database, ARRAY_LEN(cli_database));
        ast_manager_register_xml("DBGet", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_dbget);