209
204
static Statement *create_statements= NULL;
211
206
static std::vector <Statement *> query_statements;
212
static uint32_t query_statements_count;
207
static unsigned int query_statements_count;
216
void print_conclusions(Conclusions &con);
217
void print_conclusions_csv(Conclusions &con);
211
void print_conclusions(Conclusions *con);
212
void print_conclusions_csv(Conclusions *con);
218
213
void generate_stats(Conclusions *con, OptionString *eng, Stats *sptr);
219
214
uint32_t parse_comma(const char *string, std::vector <uint32_t> &range);
220
215
uint32_t parse_delimiter(const char *script, Statement **stmt, char delm);
221
216
uint32_t parse_option(const char *origin, OptionString **stmt, char delm);
222
static void drop_schema(drizzle_con_st &con, const char *db);
217
static int drop_schema(drizzle_con_st *con, const char *db);
223
218
uint32_t get_random_string(char *buf, size_t size);
224
219
static Statement *build_table_string(void);
225
220
static Statement *build_insert_string(void);
226
221
static Statement *build_update_string(void);
227
222
static Statement * build_select_string(bool key);
228
static int generate_primary_key_list(drizzle_con_st &con, OptionString *engine_stmt);
229
static void create_schema(drizzle_con_st &con, const char *db, Statement *stmt, OptionString *engine_stmt, Stats *sptr);
230
static void run_scheduler(Stats *sptr, Statement **stmts, uint32_t concur, uint64_t limit);
223
static int generate_primary_key_list(drizzle_con_st *con, OptionString *engine_stmt);
224
static int create_schema(drizzle_con_st *con, const char *db, Statement *stmt,
225
OptionString *engine_stmt, Stats *sptr);
226
static int run_scheduler(Stats *sptr, Statement **stmts, uint32_t concur,
228
extern "C" pthread_handler_t run_task(void *p);
229
extern "C" pthread_handler_t timer_thread(void *p);
231
230
void statement_cleanup(Statement *stmt);
232
231
void option_cleanup(OptionString *stmt);
233
void concurrency_loop(drizzle_con_st &con, uint32_t current, OptionString *eptr);
234
static void run_statements(drizzle_con_st &con, Statement *stmt);
235
void slap_connect(drizzle_con_st &con, bool connect_to_schema);
236
void slap_close(drizzle_con_st &con);
237
static int run_query(drizzle_con_st &con, drizzle_result_st *result, const char *query, int len);
238
void standard_deviation(Conclusions &con, Stats *sptr);
232
void concurrency_loop(drizzle_con_st *con, uint32_t current, OptionString *eptr);
233
static int run_statements(drizzle_con_st *con, Statement *stmt);
234
void slap_connect(drizzle_con_st *con, bool connect_to_schema);
235
void slap_close(drizzle_con_st *con);
236
static int run_query(drizzle_con_st *con, drizzle_result_st *result, const char *query, int len);
237
void standard_deviation (Conclusions *con, Stats *sptr);
240
239
static const char ALPHANUMERICS[]=
241
240
"0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
265
264
user_supplied_query.append(delimiter);
270
static void run_task(ThreadContext *ctx)
272
uint64_t counter= 0, queries;
273
uint64_t detach_counter;
274
uint32_t commit_counter;
275
boost::scoped_ptr<drizzle_con_st> con_ap(new drizzle_con_st);
276
drizzle_con_st &con= *con_ap.get();
277
drizzle_result_st result;
281
master_wakeup.wait();
283
slap_connect(con, true);
286
printf("connected!\n");
291
run_query(con, NULL, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
294
for (ptr= ctx->getStmt(), detach_counter= 0;
295
ptr && ptr->getLength();
296
ptr= ptr->getNext(), detach_counter++)
298
if (not opt_only_print && detach_rate && !(detach_counter % detach_rate))
301
slap_connect(con, true);
305
We have to execute differently based on query type. This should become a function.
307
bool is_failed_update= false;
308
if ((ptr->getType() == UPDATE_TYPE_REQUIRES_PREFIX) ||
309
(ptr->getType() == SELECT_TYPE_REQUIRES_PREFIX))
313
char buffer[HUGE_STRING_LENGTH];
316
This should only happen if some sort of new engine was
317
implemented that didn't properly handle UPDATEs.
319
Just in case someone runs this under an experimental engine we don't
320
want a crash so the if() is placed here.
322
assert(primary_keys.size());
323
if (primary_keys.size())
325
key_val= (uint32_t)(random() % primary_keys.size());
327
key= primary_keys[key_val].c_str();
331
length= snprintf(buffer, HUGE_STRING_LENGTH, "%.*s '%s'",
332
(int)ptr->getLength(), ptr->getString(), key);
334
if (run_query(con, &result, buffer, length))
336
if ((ptr->getType() == UPDATE_TYPE_REQUIRES_PREFIX) and commit_rate)
338
// Expand to check to see if Innodb, if so we should restart the
341
is_failed_update= true;
342
failed_update_for_transaction.fetch_and_increment();
346
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
347
SLAP_NAME, (uint32_t)length, buffer, drizzle_con_error(&con));
355
if (run_query(con, &result, ptr->getString(), ptr->getLength()))
357
if ((ptr->getType() == UPDATE_TYPE_REQUIRES_PREFIX) and commit_rate)
359
// Expand to check to see if Innodb, if so we should restart the
362
is_failed_update= true;
363
failed_update_for_transaction.fetch_and_increment();
367
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
368
SLAP_NAME, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(&con));
374
if (not opt_only_print and not is_failed_update)
376
while ((row = drizzle_row_next(&result)))
378
drizzle_result_free(&result);
382
if (commit_rate && (++commit_counter == commit_rate) and not is_failed_update)
385
run_query(con, NULL, "COMMIT", strlen("COMMIT"));
388
/* If the timer is set, and the alarm is not active then end */
389
if (opt_timer_length && timer_alarm == false)
392
/* If limit has been reached, and we are not in a timer_alarm just end */
393
if (ctx->getLimit() && queries == ctx->getLimit() && timer_alarm == false)
397
if (opt_timer_length && timer_alarm == true)
400
if (ctx->getLimit() && queries < ctx->getLimit())
406
run_query(con, NULL, "COMMIT", strlen("COMMIT"));
414
268
* commandline_options is the set of all options that can only be called via the command line.
1903
1772
if (run_query(con, NULL, query, len))
1905
1774
fprintf(stderr,"%s: Cannot drop database '%s' ERROR : %s\n",
1906
SLAP_NAME, db, drizzle_con_error(&con));
1775
internal::my_progname, db, drizzle_con_error(con));
1911
static void run_statements(drizzle_con_st &con, Statement *stmt)
1785
run_statements(drizzle_con_st *con, Statement *stmt)
1913
for (Statement *ptr= stmt; ptr && ptr->getLength(); ptr= ptr->getNext())
1789
for (ptr= stmt; ptr && ptr->getLength(); ptr= ptr->getNext())
1915
1791
if (run_query(con, NULL, ptr->getString(), ptr->getLength()))
1917
1793
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
1918
SLAP_NAME, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(&con));
1794
internal::my_progname, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(con));
1925
static void timer_thread()
1803
run_scheduler(Stats *sptr, Statement **stmts, uint32_t concur, uint64_t limit)
1806
unsigned int real_concurrency;
1807
struct timeval start_time, end_time;
1808
OptionString *sql_type;
1809
pthread_t mainthread; /* Thread descriptor */
1810
pthread_attr_t attr; /* Thread attributes */
1813
pthread_attr_init(&attr);
1814
pthread_attr_setdetachstate(&attr,
1815
PTHREAD_CREATE_DETACHED);
1817
pthread_mutex_lock(&counter_mutex);
1820
pthread_mutex_lock(&sleeper_mutex);
1822
pthread_mutex_unlock(&sleeper_mutex);
1824
real_concurrency= 0;
1826
for (y= 0, sql_type= query_options;
1827
y < query_statements_count;
1828
y++, sql_type= sql_type->getNext())
1830
unsigned int options_loop= 1;
1832
if (sql_type->getOption())
1834
options_loop= strtol(sql_type->getOption(),
1836
options_loop= options_loop ? options_loop : 1;
1839
while (options_loop--)
1841
for (uint32_t x= 0; x < concur; x++)
1844
con= new ThreadContext;
1847
fprintf(stderr, "Memory Allocation error in scheduler\n");
1850
con->setStmt(stmts[y]);
1851
con->setLimit(limit);
1854
/* now you create the thread */
1855
if (pthread_create(&mainthread, &attr, run_task,
1858
fprintf(stderr,"%s: Could not create thread\n", internal::my_progname);
1928
We lock around the initial call in case were we in a loop. This
1929
also keeps the value properly syncronized across call threads.
1867
The timer_thread belongs to all threads so it too obeys the wakeup
1868
call that run tasks obey.
1931
master_wakeup.wait();
1934
boost::mutex::scoped_lock scopedLock(timer_alarm_mutex);
1937
xtime_get(&xt, boost::TIME_UTC);
1938
xt.sec += opt_timer_length;
1940
(void)timer_alarm_threshold.timed_wait(scopedLock, xt);
1944
boost::mutex::scoped_lock scopedLock(timer_alarm_mutex);
1949
typedef boost::shared_ptr<boost::thread> Thread;
1950
typedef std::vector <Thread> Threads;
1951
static void run_scheduler(Stats *sptr, Statement **stmts, uint32_t concur, uint64_t limit)
1953
uint32_t real_concurrency;
1954
struct timeval start_time, end_time;
1959
OptionString *sql_type;
1961
master_wakeup.reset();
1963
real_concurrency= 0;
1966
for (y= 0, sql_type= query_options;
1967
y < query_statements_count;
1968
y++, sql_type= sql_type->getNext())
1970
uint32_t options_loop= 1;
1972
if (sql_type->getOption())
1974
options_loop= strtol(sql_type->getOption(),
1976
options_loop= options_loop ? options_loop : 1;
1979
while (options_loop--)
1981
for (uint32_t x= 0; x < concur; x++)
1984
con= new ThreadContext;
1987
fprintf(stderr, "Memory Allocation error in scheduler\n");
1990
con->setStmt(stmts[y]);
1991
con->setLimit(limit);
1995
/* now you create the thread */
1997
thread= Thread(new boost::thread(boost::bind(&run_task, con)));
1998
threads.push_back(thread);
2005
The timer_thread belongs to all threads so it too obeys the wakeup
2006
call that run tasks obey.
2008
if (opt_timer_length)
2011
boost::mutex::scoped_lock alarmLock(timer_alarm_mutex);
2016
thread= Thread(new boost::thread(&timer_thread));
2017
threads.push_back(thread);
2021
master_wakeup.start();
1870
if (opt_timer_length)
1872
pthread_mutex_lock(&timer_alarm_mutex);
1874
pthread_mutex_unlock(&timer_alarm_mutex);
1876
if (pthread_create(&mainthread, &attr, timer_thread,
1877
(void *)&opt_timer_length) != 0)
1879
fprintf(stderr,"%s: Could not create timer thread\n", internal::my_progname);
1884
pthread_mutex_unlock(&counter_mutex);
1885
pthread_attr_destroy(&attr);
1887
pthread_mutex_lock(&sleeper_mutex);
1889
pthread_mutex_unlock(&sleeper_mutex);
1890
pthread_cond_broadcast(&sleep_threshhold);
2023
1892
gettimeofday(&start_time, NULL);
2026
1895
We loop until we know that all children have cleaned up.
2028
for (Threads::iterator iter= threads.begin(); iter != threads.end(); iter++)
1897
pthread_mutex_lock(&counter_mutex);
1898
while (thread_counter)
1900
struct timespec abstime;
1902
set_timespec(abstime, 3);
1903
pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
1905
pthread_mutex_unlock(&counter_mutex);
2033
1907
gettimeofday(&end_time, NULL);
2035
1910
sptr->setTiming(timedif(end_time, start_time));
2036
1911
sptr->setUsers(concur);
2037
1912
sptr->setRealUsers(real_concurrency);
2038
1913
sptr->setRows(limit);
1919
pthread_handler_t timer_thread(void *p)
1921
uint32_t *timer_length= (uint32_t *)p;
1922
struct timespec abstime;
1926
We lock around the initial call in case were we in a loop. This
1927
also keeps the value properly syncronized across call threads.
1929
pthread_mutex_lock(&sleeper_mutex);
1930
while (master_wakeup)
1932
pthread_cond_wait(&sleep_threshhold, &sleeper_mutex);
1934
pthread_mutex_unlock(&sleeper_mutex);
1936
set_timespec(abstime, *timer_length);
1938
pthread_mutex_lock(&timer_alarm_mutex);
1939
pthread_cond_timedwait(&timer_alarm_threshold, &timer_alarm_mutex, &abstime);
1940
pthread_mutex_unlock(&timer_alarm_mutex);
1942
pthread_mutex_lock(&timer_alarm_mutex);
1944
pthread_mutex_unlock(&timer_alarm_mutex);
1949
pthread_handler_t run_task(void *p)
1951
uint64_t counter= 0, queries;
1952
uint64_t detach_counter;
1953
unsigned int commit_counter;
1955
drizzle_result_st result;
1958
ThreadContext *ctx= (ThreadContext *)p;
1960
pthread_mutex_lock(&sleeper_mutex);
1961
while (master_wakeup)
1963
pthread_cond_wait(&sleep_threshhold, &sleeper_mutex);
1965
pthread_mutex_unlock(&sleeper_mutex);
1967
slap_connect(&con, true);
1970
printf("connected!\n");
1975
run_query(&con, NULL, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
1978
for (ptr= ctx->getStmt(), detach_counter= 0;
1979
ptr && ptr->getLength();
1980
ptr= ptr->getNext(), detach_counter++)
1982
if (!opt_only_print && detach_rate && !(detach_counter % detach_rate))
1985
slap_connect(&con, true);
1989
We have to execute differently based on query type. This should become a function.
1991
if ((ptr->getType() == UPDATE_TYPE_REQUIRES_PREFIX) ||
1992
(ptr->getType() == SELECT_TYPE_REQUIRES_PREFIX))
1995
unsigned int key_val;
1996
char buffer[HUGE_STRING_LENGTH];
1999
This should only happen if some sort of new engine was
2000
implemented that didn't properly handle UPDATEs.
2002
Just in case someone runs this under an experimental engine we don't
2003
want a crash so the if() is placed here.
2005
assert(primary_keys.size());
2006
if (primary_keys.size())
2008
key_val= (unsigned int)(random() % primary_keys.size());
2010
key= primary_keys[key_val].c_str();
2014
length= snprintf(buffer, HUGE_STRING_LENGTH, "%.*s '%s'",
2015
(int)ptr->getLength(), ptr->getString(), key);
2017
if (run_query(&con, &result, buffer, length))
2019
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
2020
internal::my_progname, (uint32_t)length, buffer, drizzle_con_error(&con));
2027
if (run_query(&con, &result, ptr->getString(), ptr->getLength()))
2029
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
2030
internal::my_progname, (uint32_t)ptr->getLength(), ptr->getString(), drizzle_con_error(&con));
2035
if (!opt_only_print)
2037
while ((row = drizzle_row_next(&result)))
2039
drizzle_result_free(&result);
2043
if (commit_rate && (++commit_counter == commit_rate))
2046
run_query(&con, NULL, "COMMIT", strlen("COMMIT"));
2049
/* If the timer is set, and the alarm is not active then end */
2050
if (opt_timer_length && timer_alarm == false)
2053
/* If limit has been reached, and we are not in a timer_alarm just end */
2054
if (ctx->getLimit() && queries == ctx->getLimit() && timer_alarm == false)
2058
if (opt_timer_length && timer_alarm == true)
2061
if (ctx->getLimit() && queries < ctx->getLimit())
2067
run_query(&con, NULL, "COMMIT", strlen("COMMIT"));
2071
pthread_mutex_lock(&counter_mutex);
2073
pthread_cond_signal(&count_threshhold);
2074
pthread_mutex_unlock(&counter_mutex);
2042
2082
Parse records from comma seperated string. : is a reserved character and is used for options
2045
uint32_t parse_option(const char *origin, OptionString **stmt, char delm)
2086
parse_option(const char *origin, OptionString **stmt, char delm)
2048
2089
char *begin_ptr;
2200
void print_conclusions(Conclusions &con)
2244
print_conclusions(Conclusions *con)
2202
2246
printf("Benchmark\n");
2203
if (con.getEngine())
2204
printf("\tRunning for engine %s\n", con.getEngine());
2206
if (not opt_label.empty() || !opt_auto_generate_sql_type.empty())
2247
if (con->getEngine())
2248
printf("\tRunning for engine %s\n", con->getEngine());
2249
if (!opt_label.empty() || !opt_auto_generate_sql_type.empty())
2208
2251
const char *ptr= opt_auto_generate_sql_type.c_str() ? opt_auto_generate_sql_type.c_str() : "query";
2209
2252
printf("\tLoad: %s\n", !opt_label.empty() ? opt_label.c_str() : ptr);
2211
2254
printf("\tAverage Time took to generate schema and initial data: %ld.%03ld seconds\n",
2212
con.getCreateAvgTiming() / 1000, con.getCreateAvgTiming() % 1000);
2255
con->getCreateAvgTiming() / 1000, con->getCreateAvgTiming() % 1000);
2213
2256
printf("\tAverage number of seconds to run all queries: %ld.%03ld seconds\n",
2214
con.getAvgTiming() / 1000, con.getAvgTiming() % 1000);
2257
con->getAvgTiming() / 1000, con->getAvgTiming() % 1000);
2215
2258
printf("\tMinimum number of seconds to run all queries: %ld.%03ld seconds\n",
2216
con.getMinTiming() / 1000, con.getMinTiming() % 1000);
2259
con->getMinTiming() / 1000, con->getMinTiming() % 1000);
2217
2260
printf("\tMaximum number of seconds to run all queries: %ld.%03ld seconds\n",
2218
con.getMaxTiming() / 1000, con.getMaxTiming() % 1000);
2261
con->getMaxTiming() / 1000, con->getMaxTiming() % 1000);
2219
2262
printf("\tTotal time for tests: %ld.%03ld seconds\n",
2220
con.getSumOfTime() / 1000, con.getSumOfTime() % 1000);
2221
printf("\tStandard Deviation: %ld.%03ld\n", con.getStdDev() / 1000, con.getStdDev() % 1000);
2222
printf("\tNumber of queries in create queries: %"PRIu64"\n", con.getCreateCount());
2263
con->getSumOfTime() / 1000, con->getSumOfTime() % 1000);
2264
printf("\tStandard Deviation: %ld.%03ld\n", con->getStdDev() / 1000, con->getStdDev() % 1000);
2265
printf("\tNumber of queries in create queries: %"PRIu64"\n", con->getCreateCount());
2223
2266
printf("\tNumber of clients running queries: %u/%u\n",
2224
con.getUsers(), con.getRealUsers());
2267
con->getUsers(), con->getRealUsers());
2225
2268
printf("\tNumber of times test was run: %u\n", iterations);
2226
printf("\tAverage number of queries per client: %"PRIu64"\n", con.getAvgRows());
2228
uint64_t temp_val= failed_update_for_transaction;
2230
printf("\tFailed number of updates %"PRIu64"\n", temp_val);
2269
printf("\tAverage number of queries per client: %"PRIu64"\n", con->getAvgRows());
2235
void print_conclusions_csv(Conclusions &con)
2274
print_conclusions_csv(Conclusions *con)
2237
2277
char buffer[HUGE_STRING_LENGTH];
2238
2278
char label_buffer[HUGE_STRING_LENGTH];
2239
2279
size_t string_len;
2273
2313
snprintf(buffer, HUGE_STRING_LENGTH,
2274
2314
"%s,%s,%ld.%03ld,%ld.%03ld,%ld.%03ld,%ld.%03ld,%ld.%03ld,"
2275
2315
"%u,%u,%u,%"PRIu64"\n",
2276
con.getEngine() ? con.getEngine() : "", /* Storage engine we ran against */
2316
con->getEngine() ? con->getEngine() : "", /* Storage engine we ran against */
2277
2317
label_buffer, /* Load type */
2278
con.getAvgTiming() / 1000, con.getAvgTiming() % 1000, /* Time to load */
2279
con.getMinTiming() / 1000, con.getMinTiming() % 1000, /* Min time */
2280
con.getMaxTiming() / 1000, con.getMaxTiming() % 1000, /* Max time */
2281
con.getSumOfTime() / 1000, con.getSumOfTime() % 1000, /* Total time */
2282
con.getStdDev() / 1000, con.getStdDev() % 1000, /* Standard Deviation */
2318
con->getAvgTiming() / 1000, con->getAvgTiming() % 1000, /* Time to load */
2319
con->getMinTiming() / 1000, con->getMinTiming() % 1000, /* Min time */
2320
con->getMaxTiming() / 1000, con->getMaxTiming() % 1000, /* Max time */
2321
con->getSumOfTime() / 1000, con->getSumOfTime() % 1000, /* Total time */
2322
con->getStdDev() / 1000, con->getStdDev() % 1000, /* Standard Deviation */
2283
2323
iterations, /* Iterations */
2284
con.getUsers(), /* Children used max_timing */
2285
con.getRealUsers(), /* Children used max_timing */
2286
con.getAvgRows() /* Queries run */
2324
con->getUsers(), /* Children used max_timing */
2325
con->getRealUsers(), /* Children used max_timing */
2326
con->getAvgRows() /* Queries run */
2288
2328
size_t buff_len= strlen(buffer);
2289
2329
ssize_t write_ret= write(csv_file, (unsigned char*) buffer, buff_len);