
INTRODUCTION

super-smack is a tool to measure performance of a database server under load
created by concurrent multiple clients running user-defined sets of queries.
Derived from the code base of mysql-super-smack. Currently supports MySQL and
PostgreSQL

USAGE

super-smack -d db_type smack-file

SMACK FILE CONCEPTS AND SYNTAX

A lot can be learned by studything the example files in this directories,
which can be recognized by their .smack extension, which is the recommended
method. This section will cover some operating concepts that will help you
understand the syntax found in the examples, as well as the explanation of
some details.

The smack file consist of any combination objects of the following types:

query
dictionary
client
table

and the executable object "main"

You can do chmod +x on a smack file , and put

#! /usr/local/bin/super-smack at the top - then you can run the
smack file like a shell or Perl script, with mysql-super-smack being the
interpreter.

See examples for the info on the syntax of object definitions

An object definition can occur anywhere in the file before the main executable
object definition. A reference to an object must be preceded by its definition.
All objects must be defined before "main".

The members of different object can be defined in any order, with the exeption
of the executable object main, in which the members must be in the order of
execution.

Below is the discussion of different types of objects:

query

query object has the following members/attributes:

query - the sql of the query - you can reference dictionaries inside the query
using a PHP/Perl-like syntax of $dict_name

type - this can be anything -   the benchmark result is grouped  by query
type. If you want to see the performance of each query object individually,
just use a unique type for each query object.

has_result_set "y"/"n" - should the client call mysql_store_result after each
mysql_query, or should it not worry about it? If this is a select, you should
say "y", if it is an update, insert or delete, say "n"

parsed "y"/"n" - should $dict_name references be expanded into the current
value in the named dictionary, or should they be treated literaly?

dictionary

dictionary object has the following members/attributes:

type "rand"/"seq"/"unique" :
"rand" - the dictionary is initialized with a list of words, and they are
retrieved in random order
"seq" - the words are retrieved in the sequential order
"unique" - each word is generated by snprintf(buf, buf_size, template, id),
 and id is incremented by 1 

source_type "file"/"list"/"template" -
 should the dictionary be initialized from a file,
 a user-defined list, or using a template?

source  - if the source type is file, tells us which file the dictionary is in,
if list, provided a comma-delimited list of entries, if the source is a
 template, use it as a sprintf() format template.

client

client object has the following members/attributes:

user,host,db,pass - connection parameters

query_barrel - query barrel is a set of query shots. query shot is defined by
the query name and the number of times it is to be run in one shot. The client
then has a query barrel, just like a revolver. As the barrel rotates, each shot
is fired by executing the query of the shot X number of times, as speficied in
the shot definition. To specify the query shot you use the syntax of
N query_name where N is the number of times to run the query in a shot, and
to define the barrel you just concatenate the shots - see the examples for
details.

Our magic query revolver is capable of recharging itself on each revolution.
Don't set the number of shots to 200 if you need to run 200 queries - just tell
the query barrel to do 200 rounds instead - see the info on client methods
below. The reason for the shots and the rounds rather than just having one
round is to allow a greater flexibility in creating the query mix.

client methods:

init() - performs some internal initialization and starts the timer - you must
call it first
set_num_rounds(N) - set the number of time the barrel will revolve
create_threads(N) - forks off N smacker clients - after you've called you are
 multi-threaded
connect() - connects each smacker client 
unload_query_barrel() - runs the queries in the query barrel - the revolver
 will rotate num_rounds times as previously set by set_num_rounds()
collect_threads() - if we are in the report thread, wait on the smackers to
 finish their job and report the results. If we are in the smacker thread,
 forward the report to the report thread. There is only one report thread,
 and however many you've named in create_threads() smacker threads.

disconnect() - self-explanatory

table

Table section defines the pre-requisite table than needs to exist before
the test starts, and how to create it and populate it if it does not exist
or does not have the minimum number of rows.

Main section

Reading the following will make a lot more sense after you've looked at
the examples.

As you may have noticed, the you must call init() on a client before you do
anything else. This will fork off the main thread for that client ( reporting
thread), after which the main mysql-super-smack control thread will continue
parsing. So the sequence of the method calls is only signigicant for any
given client - after you have called init() on a client, the parsing itself
is already multi-threaded, and each control thread will ingore the method
calls that do not belong to its client. One should also always call connect()
only after create_thread() to avoid socket conflicts, as sockets are
shared after fork().






