From 522a62446cac132f0f1616a41f0df7e876b385eb Mon Sep 17 00:00:00 2001 From: "brian@zim.(none)" <> Date: Sun, 1 Jan 2006 20:08:45 -0800 Subject: [PATCH] Cleaned up memory allocation to be a little more staight forward (though I suspect someone will hate my sizeof() increment). Nothing really to see here. Updated comments in code. More comments are probably needed, but isn't that always the case? --- client/mysqlslap.c | 152 +++++++++++------------------------- mysql-test/t/mysqlslap.test | 4 +- 2 files changed, 47 insertions(+), 109 deletions(-) diff --git a/client/mysqlslap.c b/client/mysqlslap.c index 295665d91f5..5c34e8a0d41 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -1,4 +1,3 @@ -#include /* Copyright (C) 2005 MySQL AB This program is free software; you can redistribute it and/or modify @@ -27,28 +26,19 @@ then reporting the timing of each stage. MySQL slap runs three stages: - 1) Create table (single client) + 1) Create schema,table, and optionally any SP or data you want to beign + the test with. (single client) 2) Load test (many clients) 3) Cleanup (disconnection, drop table if specified, single client) Examples: - Supply your own create, insert and query SQL statements, with eight - clients loading data (eight inserts for each) and 50 clients querying (200 - selects for each): + Supply your own create and query SQL statements, with 50 clients + querying (200 selects for each): mysqlslap --create="CREATE TABLE A (a int);INSERT INTO A (23)" \ --query="SELECT * FROM A" --concurrency=50 --iterations=200 - Let the program build create, insert and query SQL statements with a table - of two int columns, three varchar columns, with five clients loading data - (12 inserts each), five clients querying (20 times each), and drop schema - before creating: - - mysqlslap --concurrency=5 --iterations=20 \ - --number-int-cols=2 --number-char-cols=3 \ - --auto-generate-sql - Let the program build the query SQL statement with a table of two int columns, three varchar columns, five clients querying (20 times each), don't create the table or insert the data (using the previous test's @@ -60,9 +50,9 @@ Tell the program to load the create, insert and query SQL statements from the specified files, where the create.sql file has multiple table creation - statements delimited by ';', multiple insert statements delimited by ';', - and multiple queries delimited by ';', run all the load statements with - five clients (five times each), and run all the queries in the query file + statements delimited by ';' and multiple insert statements delimited by ';'. + The --query file will have multiple queries delimited by ';', run all the + load statements, and then run all the queries in the query file with five clients (five times each): mysqlslap --drop-schema --concurrency=5 \ @@ -74,6 +64,9 @@ TODO: String length for files and those put on the command line are not setup to handle binary data. Report results of each thread into the lock file we use. + More stats + Break up tests and run them on multiple hosts at once. + Allow output to be fed into a database directly. */ @@ -156,7 +149,6 @@ struct stats { long int timing; uint users; unsigned long long rows; - stats *next; }; typedef struct conclusions conclusions; @@ -168,6 +160,7 @@ struct conclusions { long int min_timing; uint users; unsigned long long avg_rows; + // The following are not used yet unsigned long long max_rows; unsigned long long min_rows; }; @@ -192,6 +185,7 @@ static int create_schema(MYSQL *mysql, const char *db, statement *stmt, static int run_scheduler(stats *sptr, statement *stmts, uint concur, ulonglong limit); int run_task(statement *stmt, ulong limit); +void statement_cleanup(statement *stmt); static const char ALPHANUMERICS[]= "0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz"; @@ -199,31 +193,6 @@ static const char ALPHANUMERICS[]= #define ALPHANUMERICS_SIZE (sizeof(ALPHANUMERICS)-1) - -#ifdef DELETE_LATER -/* Return the time in ms between two timevals */ -static double timedif (struct timeval end, struct timeval begin) -{ - double seconds; - DBUG_ENTER("timedif"); - - seconds= (double)(end.tv_usec - begin.tv_usec)/1000000; - DBUG_PRINT("info", ("end.tv_usec %d - begin.tv_usec %d = " - "%d microseconds ( fseconds %f)", - end.tv_usec, begin.tv_usec, - (end.tv_usec - begin.tv_usec), - seconds)); - seconds += (double)(end.tv_sec - begin.tv_sec); - DBUG_PRINT("info", ("end.tv_sec %d - begin.tv_sec %d = " - "%d seconds (fseconds %f)", - end.tv_sec, begin.tv_sec, - (end.tv_sec - begin.tv_sec), seconds)); - - DBUG_PRINT("info", ("returning time %f seconds", seconds)); - DBUG_RETURN(seconds); -} -#endif - static long int timedif(struct timeval a, struct timeval b) { register int us, s; @@ -236,13 +205,13 @@ static long int timedif(struct timeval a, struct timeval b) } - - int main(int argc, char **argv) { MYSQL mysql; int client_flag= 0; int x; + unsigned long long client_limit; + statement *eptr; DBUG_ENTER("main"); MY_INIT(argv[0]); @@ -300,31 +269,28 @@ int main(int argc, char **argv) } // Main iterations loop - unsigned long long client_limit; - eptr= engine_statements; do { /* For the final stage we run whatever queries we were asked to run */ uint *current; conclusions conclusion; + for (current= concurrency; current && *current; current++) { - stats *head_sptr= NULL; // Not assigning NULL causes compiler to complain - stats *sptr= NULL; // Not assigning NULL causes compiler to complain - stats *nptr= NULL; // Just used for deallocation + stats *head_sptr; + stats *sptr; + + head_sptr= (stats *)my_malloc(sizeof(stats) * *current, MYF(MY_ZEROFILL)); bzero(&conclusion, sizeof(conclusions)); + if (num_of_query) client_limit= num_of_query / *current; else client_limit= actual_queries; - for (x= 0, sptr= head_sptr= - (stats *)my_malloc(sizeof(stats), MYF(MY_ZEROFILL)); - x < iterations; x++, - sptr= sptr->next= (stats *)my_malloc(sizeof(stats), MYF(MY_ZEROFILL)) - ) + for (x= 0, sptr= head_sptr; x < iterations; x++, sptr+= sizeof(stats)) { /* We might not want to load any data, such as when we are calling @@ -339,18 +305,15 @@ int main(int argc, char **argv) run_scheduler(sptr, query_statements, *current, client_limit); } + generate_stats(&conclusion, eptr, head_sptr); + if (!opt_silent) print_conclusions(&conclusion); if (opt_csv_str) print_conclusions_csv(&conclusion); - for (sptr= head_sptr; sptr;) - { - nptr= sptr->next; - my_free((byte *)sptr, MYF(0)); - sptr= nptr; - } + my_free((byte *)head_sptr, MYF(0)); } if (!opt_preserve) @@ -370,44 +333,9 @@ int main(int argc, char **argv) my_free((byte *)concurrency, MYF(0)); - if (create_statements) - { - statement *ptr, *nptr; - for (ptr= create_statements; ptr;) - { - nptr= ptr->next; - if (ptr->string) - my_free(ptr->string, MYF(0)); - my_free((byte *)ptr, MYF(0)); - ptr= nptr; - } - } - - if (engine_statements) - { - statement *ptr, *nptr; - for (ptr= engine_statements; ptr;) - { - nptr= ptr->next; - if (ptr->string) - my_free(ptr->string, MYF(0)); - my_free((byte *)ptr, MYF(0)); - ptr= nptr; - } - } - - if (query_statements) - { - statement *ptr, *nptr; - for (ptr= query_statements; ptr;) - { - nptr= ptr->next; - if (ptr->string) - my_free(ptr->string, MYF(0)); - my_free((byte *)ptr, MYF(0)); - ptr= nptr; - } - } + statement_cleanup(create_statements); + statement_cleanup(engine_statements); + statement_cleanup(query_statements); #ifdef HAVE_SMEM if (shared_memory_base_name) @@ -787,13 +715,7 @@ get_options(int *argc,char ***argv) exit(1); } - if (concurrency_str) - parse_comma(concurrency_str, &concurrency); - else - { - concurrency= (uint *)my_malloc(sizeof(uint) * 2, MYF(MY_ZEROFILL)); - concurrency[0]= 1; - } + parse_comma(concurrency_str ? concurrency_str : "1", &concurrency); if (lock_directory) snprintf(lock_file_str, FN_REFLEN, "%s/%s", lock_directory, MYSLAPLOCK); @@ -1270,7 +1192,7 @@ generate_stats(conclusions *con, statement *eng, stats *sptr) con->avg_rows= sptr->rows; // With no next, we know it is the last element that was malloced - for (ptr= sptr, x= 0; x < iterations; ptr= ptr->next, x++) + for (ptr= sptr, x= 0; x < iterations; ptr+= sizeof(stats), x++) { con->avg_timing+= ptr->timing; @@ -1286,3 +1208,19 @@ generate_stats(conclusions *con, statement *eng, stats *sptr) else con->engine= NULL; } + +void +statement_cleanup(statement *stmt) +{ + statement *ptr, *nptr; + if (!stmt) + return; + + for (ptr= stmt; ptr; ptr= nptr) + { + nptr= ptr->next; + if (ptr->string) + my_free(ptr->string, MYF(0)); + my_free((byte *)ptr, MYF(0)); + } +} diff --git a/mysql-test/t/mysqlslap.test b/mysql-test/t/mysqlslap.test index b3cbebe4ff4..8234659b2e6 100644 --- a/mysql-test/t/mysqlslap.test +++ b/mysql-test/t/mysqlslap.test @@ -4,10 +4,10 @@ --exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql ---exec $MYSQL_SLAP --only-print --concurrency=1 --iterations=20 --query="select * from t1" --create="CREATE TABLE t1 (id int, name varchar(64)); INSERT INTO t1 VALUES (1, 'This is a test')" --delimiter=";" +--exec $MYSQL_SLAP --only-print --iterations=20 --query="select * from t1" --create="CREATE TABLE t1 (id int, name varchar(64)); INSERT INTO t1 VALUES (1, 'This is a test')" --delimiter=";" --exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --query="select * from t1" --create="CREATE TABLE t1 (id int, name varchar(64)); INSERT INTO t1 VALUES (1, 'This is a test')" --delimiter=";" ---exec $MYSQL_SLAP --only-print --concurrency=1 --iterations=1 --delimiter=";" --query="select * from t1;select * from t2" --create="CREATE TABLE t1 (id int, name varchar(64)); create table t2(foo1 varchar(32), foo2 varchar(32)); INSERT INTO t1 VALUES (1, 'This is a test'); insert into t2 values ('test', 'test2')" --engine="heap,myisam" +--exec $MYSQL_SLAP --only-print --delimiter=";" --query="select * from t1;select * from t2" --create="CREATE TABLE t1 (id int, name varchar(64)); create table t2(foo1 varchar(32), foo2 varchar(32)); INSERT INTO t1 VALUES (1, 'This is a test'); insert into t2 values ('test', 'test2')" --engine="heap,myisam" --exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --delimiter=";" --query="select * from t1;select * from t2" --create="CREATE TABLE t1 (id int, name varchar(64)); create table t2(foo1 varchar(32), foo2 varchar(32)); INSERT INTO t1 VALUES (1, 'This is a test'); insert into t2 values ('test', 'test2')"