John McCaskey wrote:
Hello again,

I modified your threading code to use a thread pool. Here are my results:

Hello,

I modified the thread pool a bit to get rid of that lock ASAP. It is safe
to get rid of that lock right after mysql_store_results.

http://dev.mysql.com/doc/mysql/en/threaded-clients.html

The conclusion I draw from all this is that if you have a very fast
connection to your db its best NOT to use threading at all if your queries
are simple and you expect the results fast.

Here is another interesting thing though, if multi threading is used, I
got the best results by using 2 connections, I am also using dual CPUs
(i%CONNECTIONS). I guess everyone can draw its own conclusions depending
on his needs but for me, and since I only need to do *few, simple, local*
queries, looks like I can "live" without the multi thread over head for
now. The more complex are the queries, slower the connections and higher
the response time is, (the slower the answer you get in general) then
multi threading could be a winner.

-- Clearly the winner ---

Thread Safe OFF
DB Connections: 1, Total Queries: 10000
        8.20 real         1.21 user         4.88 sys
Thread Safe OFF
DB Connections: 1, Total Queries: 10000
        8.19 real         1.12 user         4.98 sys

pooled-threading2.c (moved that unlock right after mysql_store_results):

Thread Safe ON
DB Connections: 1, Threads: 100, Total Queries: 10000
       13.20 real         2.91 user         8.07 sys
Thread Safe ON
DB Connections: 1, Threads: 100, Total Queries: 10000
       13.11 real         2.69 user         8.12 sys

Thread Safe ON
DB Connections: 2, Threads: 100, Total Queries: 10000
       12.70 real         2.70 user         8.08 sys
Thread Safe ON
DB Connections: 2, Threads: 100, Total Queries: 10000
       12.74 real         2.89 user         7.89 sys

Thread Safe ON
DB Connections: 3, Threads: 100, Total Queries: 10000
       12.81 real         2.87 user         8.01 sys
Thread Safe ON
DB Connections: 3, Threads: 100, Total Queries: 10000
       12.90 real         2.91 user         8.04 sys

Thread Safe ON
DB Connections: 4, Threads: 100, Total Queries: 10000
       12.88 real         2.89 user         8.03 sys
Thread Safe ON
DB Connections: 4, Threads: 100, Total Queries: 10000
       12.89 real         2.95 user         8.00 sys

Thread Safe ON
DB Connections: 5, Threads: 100, Total Queries: 10000
       13.05 real         2.68 user         8.34 sys
Thread Safe ON
DB Connections: 5, Threads: 100, Total Queries: 10000
       12.92 real         2.84 user         8.11 sys

Thread Safe ON
DB Connections: 10, Threads: 100, Total Queries: 10000
       13.05 real         3.00 user         8.00 sys
Thread Safe ON
DB Connections: 10, Threads: 100, Total Queries: 10000
       12.98 real         2.79 user         8.18 sys

Thread Safe ON
DB Connections: 15, Threads: 100, Total Queries: 10000
       13.08 real         2.72 user         8.30 sys
Thread Safe ON
DB Connections: 15, Threads: 100, Total Queries: 10000
       13.08 real         2.71 user         8.31 sys

Thread Safe ON
DB Connections: 20, Threads: 100, Total Queries: 10000
       13.18 real         2.94 user         8.16 sys
Thread Safe ON
DB Connections: 20, Threads: 100, Total Queries: 10000
       13.17 real         2.95 user         8.12 sys
------------------------------------------------------------------
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <mysql.h>

#define MAX 100
#define CONNECTIONS 2

typedef struct db_donfig {
        char host[16];
        char user[16];
        char pass[16];
        char name[16];
        unsigned int port;
        char *socket;
} db_config;

typedef struct db_mutex {
        MYSQL *db;
        pthread_mutex_t lock;
} db_mutex;

db_mutex dbm[CONNECTIONS];

void            *db_pthread(void *arg);
static           void db_die(MYSQL *db, char *fmt, ...);
MYSQL           *db_connect(MYSQL *db, db_config *dbc);
void             db_disconnect(MYSQL *db);
long             db_query(MYSQL *db, pthread_mutex_t *lock, const char *query);

int main(int argc, char **argv) {
        int i;
        pthread_t pthread[MAX];
        db_config dbc;

        strcpy(dbc.host,"localhost");
        strcpy(dbc.user,"root");
        strcpy(dbc.pass,"");
        strcpy(dbc.name,"");
        dbc.port = 3306;
        dbc.socket = NULL;

        if (!mysql_thread_safe())
                fprintf(stderr, "Thread Safe OFF\n");
        else
                fprintf(stderr, "Thread Safe ON\n");
        fprintf(stdout, "DB Connections: %d, Threads: %d, Total Queries: %d\n", 
CONNECTIONS, MAX, MAX * MAX);

        // pre initialize connections and locks
        for (i = 0; i < CONNECTIONS; ++i) {
                dbm[i].db = db_connect(dbm[i].db, &dbc);
                pthread_mutex_init(&dbm[i].lock, NULL);
        }

        // pthread_setconcurrency(4);
        // fire up the threads
        for (i = 0; i < MAX; ++i)
                pthread_create(&pthread[i], NULL, db_pthread, (void 
*)(i%CONNECTIONS));
        // wait for threads to finish
        for (i = 0; i < MAX; ++i)
                pthread_join(pthread[i], 0);

        for (i = 0; i < CONNECTIONS; ++i) {
                pthread_mutex_destroy(&dbm[i].lock);
                db_disconnect(dbm[i].db);
        }

        exit(EXIT_SUCCESS);
}

void *db_pthread(void *arg) {
        int i, j;
        i = (int) arg;

        mysql_thread_init();
        for(j = 0; j < MAX; ++j)
                db_query(dbm[i].db, &(dbm[i].lock), "show status");
        mysql_thread_end();
        pthread_exit((void *)0);
}

static void db_die(MYSQL *db, char *fmt, ...) {
        va_list ap;
        va_start(ap, fmt);
        vfprintf(stderr, fmt, ap);
        va_end(ap);
        (void)putc('\n', stderr);
        db_disconnect(db);
        exit(EXIT_FAILURE);
}

MYSQL *db_connect(MYSQL *db, db_config *dbc) {
        if ( !(db = mysql_init(db)) )
                db_die(db, "mysql_init failed: %s", mysql_error(db));
        else {
                if ( !mysql_real_connect(db, dbc->host, dbc->user, dbc->pass, 
dbc->name, dbc->port, dbc->socket, 0) )
                        db_die(db, "mysql_real_connect failed: %s", 
mysql_error(db));
        }
        return (db);
}

void db_disconnect(MYSQL *db) {
        if (db)
                mysql_close(db);
}

long db_query(MYSQL *db, pthread_mutex_t *lock, const char *query) {
        long ret;

        // lock must be called before mysql_query
        pthread_mutex_lock(lock);
        ret = mysql_query(db, query);
        // if query failed, exit with db error
        if (ret != 0) {
                // Get rid of the lock first
                pthread_mutex_unlock(lock);
                db_die(db, "mysql_query failed: %s", mysql_error(db));
        }
        // if query succeeded
        else {
                MYSQL_RES *res;

                res = mysql_store_result(db);
                // Get rid of the lock ASAP, only safe after mysql_store_result
                pthread_mutex_unlock(lock);
                // if there are rows
                if (res) {
                        MYSQL_ROW row, end_row;
                        unsigned int num_fields;

                        num_fields = mysql_num_fields(res);
                        while ( (row = mysql_fetch_row(res)) )
                                for (end_row = row + num_fields; row < end_row; 
++row)
                                        ++ret;
                        mysql_free_result(res);
                }
                // if there are no rows, should there be any ?
                else {
                        // if query was not a SELECT, return with affected rows
                        if(mysql_field_count(db) == 0)
                                ret = mysql_affected_rows(db);
                        // there should be data, exit with db error
                        else
                                db_die(db, "mysql_store_result failed: %s", 
mysql_error(db));
                }
        }
        return (ret);
}


--
MySQL General Mailing List
For list archives: http://lists.mysql.com/mysql
To unsubscribe:    http://lists.mysql.com/[EMAIL PROTECTED]

Reply via email to