{"id":203,"date":"2018-11-30T17:44:23","date_gmt":"2018-11-30T17:44:23","guid":{"rendered":"http:\/\/www.hammerdb.com\/blog\/?p=203"},"modified":"2018-12-10T14:32:23","modified_gmt":"2018-12-10T14:32:23","slug":"hammerdb-concepts-and-architecture","status":"publish","type":"post","link":"https:\/\/www.hammerdb.com\/blog\/uncategorized\/hammerdb-concepts-and-architecture\/","title":{"rendered":"HammerDB Concepts and Architecture"},"content":{"rendered":"<p>HammerDB is open source and all of the source code is available at the sourceforge Git development site here <a href=\"https:\/\/sourceforge.net\/p\/hammerdb\/code\/ci\/master\/tree\/\">https:\/\/sourceforge.net\/p\/hammerdb\/code\/ci\/master\/tree\/<\/a> or the github mirror here <a href=\"https:\/\/github.com\/sm-shaw\/HammerDB\">https:\/\/github.com\/sm-shaw\/HammerDB<\/a>.\u00a0 This Git repository is updated with every release.\u00a0 In fact all of this source code is also included in readable form with each and every release.\u00a0 However if you have downloaded the source code and are looking to add features or make modifications such as adding new databases you may be wondering once you have the source code where to start. This guide to HammerDB concepts and architectures is aimed\u00a0 at helping you understand how HammerDB is built and how it can be extended and modified.<\/p>\n<h3>Programming Languages<\/h3>\n<p>When you download the source code for HammerDB you can see that the programming language it is written in is called <a href=\"http:\/\/www.tcl.tk\">TCL<\/a> .\u00a0 TCL is a dynamic or interpreted language where the code is compiled into bytecode at runtime.\u00a0 It is important to understand at the outset that HammerDB is written in TCL because of the unique threading capabilities that TCL brings. This article <a href=\"https:\/\/dzone.com\/articles\/threads-done-right-with-tcl\">Threads Done Right&#8230; With Tcl<\/a> gives an excellent overview of these capabilities and it should be clear that to build a scalable benchmarking tool this thread performance and scalability is key.\u00a0 In contrast for example Python has the Global Interpreter Lock or GIL &#8211; &#8220;<em>the global interpreter lock, or GIL<\/em><i>, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython&#8217;s memory management is not thread-safe<\/i>&#8220;. Therefore only TCL provides the foundation for building a tool such as HammerDB although <a href=\"https:\/\/www.hammerdb.com\/blog\/uncategorized\/how-to-use-python-with-hammerdb\/\">Python can be loaded in the threads if desired<\/a>.\u00a0 If you are not familiar with TCL you can also see that it is closely associated with a graphical user interface toolkit called TK.\u00a0 For HammerDB if you run the command-line version you are using TCL only, if you are running the graphical environment you are using TCL and TK. (Note that for the features used HammerDB will only run with TCL\/TK 8.6 or above).\u00a0 So if you have downloaded the source code or the pre-packaged version and look for example in files under the src directory you will see a number of files with a .tcl extension that you can read &#8211; these are identical in both the source code and the pre-packaged version.\u00a0\u00a0 It is of note that we have not discussed the operating system yet, that is because the source code and the code included with the pre-packaged versions is identical whether it is running on Linux or Windows on x86-64 architecture (or any other platform).\u00a0 That is a slight exaggeration as there are some architectural differences (such as command-line console interaction) however these can be managed with a statement such as follows:<\/p>\n<pre>if {[string match windows $::tcl_platform(platform)]} {<\/pre>\n<p>Otherwise the code is the same on all platforms.\u00a0 Clearly however there is a difference between platforms as you can tell from the <a href=\"https:\/\/www.hammerdb.com\/download.html\">download page<\/a> and when you download the pre-packaged version you have and additional bin and lib directories that are (mostly) unique to a particular platform. These bin and lib directories are not included with the source code.\u00a0 TCL was designed as a language to be closely tied with C\/C++ and at this lower level there is the compiled TCL (tclsh) or TCL\/TK (wish) interpreter and supporting libraries.\u00a0 You can download and compile TCL\/TK 8.6 or above yourself and replace the existing interpreter to be able to run the HammerDB interface from the source code by adding the bin and lib directories.\u00a0 However HammerDB will not be able to connect to a database yet and the librarycheck command included with the CLI gives an indication why.<\/p>\n<pre>HammerDB CLI v3.1\r\nCopyright (C) 2003-2018 Steve Shaw\r\nType \"help\" for a list of commands\r\nThe xml is well-formed, applying configuration\r\nhammerdb&gt;librarycheck\r\nChecking database library for Oracle\r\nSuccess ... loaded library Oratcl for Oracle\r\nChecking database library for MSSQLServer\r\nSuccess ... loaded library tclodbc for MSSQLServer\r\nChecking database library for Db2\r\nSuccess ... loaded library db2tcl for Db2\r\nChecking database library for MySQL\r\nSuccess ... loaded library mysqltcl for MySQL\r\nChecking database library for PostgreSQL\r\nSuccess ... loaded library Pgtcl for PostgreSQL\r\nChecking database library for Redis\r\nSuccess ... loaded library redis for Redis\r\n\r\nhammerdb&gt;<\/pre>\n<h3>Database Extensions<\/h3>\n<p>Also written in C HammerDB includes the pre-compiled extensions to the native interfaces for the databases that HammerDB supports as well as other supporting packages for functions such as graphing. Some of these packages have been modified from the original open source packages to ensure the correct functionality for HammerDB. All extensions have been compiled with gcc on Linux and MSVC on Windows for the x86-64 platform and require the presence of the compatible database library at runtime. For commercial databases this third-party library is the only non-open source component of the stack.<\/p>\n<table class=\"mkup_data\" style=\"height: 316px;\">\n<tbody>\n<tr class=\"mkup_tr\" style=\"height: 26px;\">\n<th class=\"mkup_th\" style=\"height: 26px; width: 262.717px;\">Database<\/th>\n<th class=\"mkup_th\" style=\"height: 26px; width: 283.483px;\">Extension<\/th>\n<\/tr>\n<tr class=\"mkup_trodd\" style=\"height: 26px;\">\n<td class=\"mkup_td\" style=\"height: 26px; width: 262.717px;\"><a class=\"mkup_a mkup_known\" href=\"https:\/\/wiki.tcl-lang.org\/page\/Oracle\">Oracle<\/a>\/TimesTen<\/td>\n<td class=\"mkup_td\" style=\"height: 26px; width: 283.483px;\"><a class=\"mkup_a mkup_known\" href=\"https:\/\/wiki.tcl-lang.org\/page\/Oratcl\">Oratcl<\/a> 4.6<\/td>\n<\/tr>\n<tr class=\"mkup_treven\" style=\"height: 53px;\">\n<td class=\"mkup_td\" style=\"height: 53px; width: 262.717px;\">MS SQL Server\/Linux and Windows<\/td>\n<td class=\"mkup_td\" style=\"height: 53px; width: 283.483px;\">Debian patch version of <a class=\"mkup_a mkup_known\" href=\"https:\/\/wiki.tcl-lang.org\/page\/Tclodbc\">TclODBC<\/a> 2.5.1 updated to 2.5.2<\/td>\n<\/tr>\n<tr class=\"mkup_trodd\" style=\"height: 53px;\">\n<td class=\"mkup_td\" style=\"height: 53px; width: 262.717px;\">IBM <a class=\"mkup_a mkup_known\" href=\"https:\/\/wiki.tcl-lang.org\/page\/DB2\">Db2<\/a><\/td>\n<td class=\"mkup_td\" style=\"height: 53px; width: 283.483px;\">updated version of <a class=\"mkup_a mkup_known\" href=\"https:\/\/wiki.tcl-lang.org\/page\/db2tclBelinksy\">db2tclBelinksy<\/a> to add bind variable support as version 2.0.0<\/td>\n<\/tr>\n<tr class=\"mkup_treven\" style=\"height: 26px;\">\n<td class=\"mkup_td\" style=\"height: 26px; width: 262.717px;\">MariaDB\/<a class=\"mkup_a mkup_known\" href=\"https:\/\/wiki.tcl-lang.org\/page\/MySQL\">MySQL<\/a>\/Amazon Aurora<\/td>\n<td class=\"mkup_td\" style=\"height: 26px; width: 283.483px;\"><a class=\"mkup_a mkup_known\" href=\"https:\/\/wiki.tcl-lang.org\/page\/mysqltcl\">MySQLTcl<\/a> version 3.052<\/td>\n<\/tr>\n<tr class=\"mkup_trodd\" style=\"height: 53px;\">\n<td class=\"mkup_td\" style=\"height: 53px; width: 262.717px;\"><a class=\"mkup_a mkup_known\" href=\"https:\/\/wiki.tcl-lang.org\/page\/PostgreSQL\">PostgreSQL<\/a>\/Greenplum\/Amazon Redshift<\/td>\n<td class=\"mkup_td\" style=\"height: 53px; width: 283.483px;\"><a class=\"mkup_a mkup_known\" href=\"https:\/\/wiki.tcl-lang.org\/page\/Pgtcl\">PgTcl<\/a> Pgtclng version 2.1.1<\/td>\n<\/tr>\n<tr class=\"mkup_treven\" style=\"height: 26px;\">\n<td class=\"mkup_td\" style=\"height: 26px; width: 262.717px;\"><a class=\"mkup_a mkup_known\" href=\"https:\/\/wiki.tcl-lang.org\/page\/redis\">Redis<\/a><\/td>\n<td class=\"mkup_td\" style=\"height: 26px; width: 283.483px;\">In-built pure TCL client<\/td>\n<\/tr>\n<tr class=\"mkup_trodd\" style=\"height: 53px;\">\n<td class=\"mkup_td\" style=\"height: 53px; width: 262.717px;\">Trafodion SQL on Hadoop (Deprecated in HammerDB v3.0 )<\/td>\n<td class=\"mkup_td\" style=\"height: 53px; width: 283.483px;\"><a class=\"mkup_a mkup_known\" href=\"https:\/\/wiki.tcl-lang.org\/page\/TDBC\">TDBC<\/a> included with TCL<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Other Extensions<\/h3>\n<table class=\"mkup_data\">\n<tbody>\n<tr class=\"mkup_tr\">\n<th class=\"mkup_th\">Functionality<\/th>\n<th class=\"mkup_th\">Extension<\/th>\n<\/tr>\n<tr class=\"mkup_trodd\">\n<td class=\"mkup_td\"><a href=\"https:\/\/wiki.tcl-lang.org\/page\/List+of+ttk+Themes\">Clearlooks<\/a><\/td>\n<td class=\"mkup_td\">GUI Theme for Linux (but can be used on Windows)<\/td>\n<\/tr>\n<tr class=\"mkup_treven\">\n<td class=\"mkup_td\"><a href=\"https:\/\/wiki.tcl-lang.org\/page\/Expect\">Expect<\/a><\/td>\n<td class=\"mkup_td\">Console functionality for command-line functionality on Linux<\/td>\n<\/tr>\n<tr class=\"mkup_trodd\">\n<td class=\"mkup_td\"><a href=\"http:\/\/twapi.magicsplat.com\/\">tWAPI<\/a><\/td>\n<td class=\"mkup_td\">TCL Windows API used for command-line and CPU agent functionality on Windows<\/td>\n<\/tr>\n<tr class=\"mkup_treven\">\n<td class=\"mkup_td\"><a href=\"https:\/\/github.com\/wjoye\/tkblt\">tkblt<\/a><\/td>\n<td class=\"mkup_td\">BLT graphical package extension for metrics for both Linux and Windows<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Pure Tcl Modules<\/h3>\n<p>In addition to compiled extensions there are also a number of <a href=\"https:\/\/wiki.tcl-lang.org\/page\/Tcl+Modules\">TCL modules<\/a> located in the modules directory, these extensions are similar to the packages in the lib directory however the main distinction is that almost all of these modules are written in TCL rather than compiled extensions written in C.\u00a0 These modules may also call additional packages for example as shown below the ReadLine module calls either Expect or tWAPI depending on the platform.<\/p>\n<pre>package provide TclReadLine 1.2\r\n#TclReadLine2 modified to use Expect on Linux and Twapi on Windows\r\nif {[string match windows $::tcl_platform(platform)]} {\r\npackage require twapi\r\npackage require twapi_input\r\n...\r\n}\r\n} else {\r\npackage require Expect<\/pre>\n<h3>Loading Extensions and Modules<\/h3>\n<p>The key command for loading extensions and modules is &#8220;package require&#8221;, for example the following extract at the top of the Oracle driver script shows the loading of the compiled Oratcl package as well as the common functions module for the TPC-C workload.<\/p>\n<pre>#!\/usr\/local\/bin\/tclsh8.6\r\nset library Oratcl ;# Oracle OCI Library\r\n#LOAD LIBRARIES AND MODULES\r\nif [catch {package require $library} message] { error \"Failed to load $library - $message\" }\r\nif [catch {::tcl::tm::path add modules} ] { error \"Failed to find modules directory\" }\r\nif [catch {package require tpcccommon} ] { error \"Failed to load tpcc common functions\" } else { namespace import tpcccommon::* }<\/pre>\n<p><span style=\"font-size: 12pt;\">It should be clear that HammerDB is easy to extend by adding a new package into the lib (compiled) or modules (Pure TCL) directories and an example of how this is done is shown with adding <a href=\"https:\/\/www.hammerdb.com\/blog\/uncategorized\/how-to-use-python-with-hammerdb\/\">Python<\/a> support. <span style=\"font-size: 12pt;\">The include directory contains the platform specific C header files for this purpose. <\/span><br \/>\n<\/span><\/p>\n<h3>Agent<\/h3>\n<p><span style=\"font-size: 12pt;\">The agent directory contains the agent code to be run on the system under test to gather the CPU utilisation information. On Linux this runs the mpstat command on Windows mpstat is provided by HammerDB.<br \/>\n<\/span><\/p>\n<h3>Images<\/h3>\n<p>The images directory contains TCL files with the images used by HammerDB encoded in base64 format.<\/p>\n<h3>Config<\/h3>\n<p>The configuration for HammerDB is defined by a number of XML files in the config directory.\u00a0 HammerDB is modular meaning that this configuration determines the files and directories to load from the src directory at runtime.\u00a0 At the top level is the database.xml that determines the other database configurations to load. Note that the commands field in this file only determines which words to highlight in the graphical text editor rather than defining the commands themselves.<\/p>\n<h3>Starting HammerDB<\/h3>\n<p>When you start HammerDB GUI on Linux the hammerdb file is a bash script file that calls the Linux compiled wish (window shell) executable that then runs the TCL commands incorporated within that shell file. On Windows there is an external batch file that calls the Windows compiled wish and then runs TCL commands within the hammerdb file.\u00a0 For the command line it is the TCL shell that is run rather than wish.\u00a0 The hammerdb file acts as a loader that loads the modules, the icon images and the generic source, the XML based configuration is then loaded followed by the database specific components dependent on this configuration.\u00a0 The GUI or command line interface is then started.\u00a0 As virtual users are started the database specific packages and workload specific modules are loaded into the virtual user threads. The following diagram illustrates the process. Note that as the diagram illustrates most of the code is shared between both command-line and GUI implementations and what and how the virtual users run this code is identical, therefore both GUI and commmand-line produce identical results.<\/p>\n<p><a href=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/hdbarch.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-224 size-full\" src=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/hdbarch.png\" alt=\"\" width=\"1191\" height=\"720\" srcset=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/hdbarch.png 1191w, https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/hdbarch-300x181.png 300w, https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/hdbarch-768x464.png 768w, https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/hdbarch-1024x619.png 1024w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/a><\/p>\n<p>XML to Dict<\/p>\n<p>As HammerDB is modular under the src directory is a generic directory for shared source and a directory for each of the databases that has the same name as the XML configuration file for that database in the config directory.\u00a0 HammerDB reads the XML at startup and manages the parameters internally in a 2 level nested dict structure per database.\u00a0\u00a0 For example for MySQL the dict is shown and the retrieval of a single value.<\/p>\n<pre>HammerDB CLI v3.1\r\nCopyright (C) 2003-2018 Steve Shaw\r\nType \"help\" for a list of commands\r\nThe xml is well-formed, applying configuration\r\nhammerdb&gt;puts $configmysql\r\nconnection {mysql_host 127.0.0.1 mysql_port 3306} tpcc {mysql_count_ware 1 mysql_num_vu 1 mysql_user root mysql_pass mysql mysql_dbase tpcc mysql_storage_engine innodb mysql_partition false mysql_total_iterations 1000000 mysql_raiseerror false mysql_keyandthink false mysql_driver test mysql_rampup 2 mysql_duration 5 mysql_allwarehouse false mysql_timeprofile false} tpch {mysql_scale_fact 1 mysql_tpch_user root mysql_tpch_pass mysql mysql_tpch_dbase tpch mysql_num_tpch_threads 1 mysql_tpch_storage_engine myisam mysql_total_querysets 1 mysql_raise_query_error false mysql_verbose false mysql_refresh_on false mysql_update_sets 1 mysql_trickle_refresh 1000 mysql_refresh_verbose false mysql_cloud_query false}\r\n\r\nhammerdb&gt;puts [ dict get $configmysql connection mysql_host ]\r\n127.0.0.1\r\n\r\nhammerdb&gt;<\/pre>\n<p>As the options boxes in the GUI are filled out or values set at the command-line these values are stored and retrieved from these underlying dicts.\u00a0 At the top level the database.xml file determines the database specific data is read and the GUI populated at runtime rather than being fixed. For example changing the description field in the database.xml file as follows:<\/p>\n<pre>&lt;name&gt;MySQL&lt;\/name&gt;\r\n&lt;description&gt;MariaDB&lt;\/description&gt;\r\n&lt;prefix&gt;mysql&lt;\/prefix&gt;\r\n&lt;library&gt;mysqltcl&lt;\/library&gt;\r\n&lt;workloads&gt;TPC-C TPC-H&lt;\/workloads&gt;\r\n&lt;commands&gt;mysql::sel mysqluse mysqlescape mysqlsel mysqlnext mysqlseek mysqlmap mysqlexec mysqlclose mysqlinfo mysqlresult mysqlcol mysqlstate mysqlinsertid mysqlquery mysqlendquery mysqlbaseinfo mysqlping mysqlchangeuser mysqlreceive&lt;\/commands&gt;\r\n&lt;\/mysql&gt;<\/pre>\n<p>Will then display as follows in the interface.<\/p>\n<p><a href=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/mdb.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-229\" src=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/mdb.png\" alt=\"\" width=\"815\" height=\"676\" srcset=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/mdb.png 815w, https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/mdb-300x249.png 300w, https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/mdb-768x637.png 768w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/a><\/p>\n<p>Also note that the library field allows another library interface to be modified and recompiled or multiple version of libraries used for different databases.<\/p>\n<p>Once the XML configuration is loaded the database specific files are loaded according to a directory in the database name and file names determined by prefix and the following purpose.<\/p>\n<pre>hammerdb&gt;print db\r\nDatabase Oracle set.\r\nTo change do: dbset db prefix, one of:\r\nOracle = ora MSSQLServer = mssqls Db2 = db2 MySQL = mysql PostgreSQL = pg Redis = redis\r\nhammerdb&gt;<\/pre>\n<table class=\"mkup_data\" style=\"height: 210px;\">\n<tbody>\n<tr class=\"mkup_tr\" style=\"height: 26px;\">\n<th class=\"mkup_th\" style=\"width: 101.033px; height: 26px;\">Extension<\/th>\n<th class=\"mkup_th\" style=\"width: 463.167px; height: 26px;\">Purpose<\/th>\n<\/tr>\n<tr class=\"mkup_trodd\" style=\"height: 26px;\">\n<td class=\"mkup_td\" style=\"width: 101.033px; height: 26px;\">met<\/td>\n<td class=\"mkup_td\" style=\"width: 463.167px; height: 26px;\">Graphical metrics, currently only completed for Oracle<\/td>\n<\/tr>\n<tr class=\"mkup_treven\" style=\"height: 26px;\">\n<td class=\"mkup_td\" style=\"width: 101.033px; height: 26px;\">olap<\/td>\n<td class=\"mkup_td\" style=\"width: 463.167px; height: 26px;\">Analytic workloads, currently TPC-H related build and driver<\/td>\n<\/tr>\n<tr class=\"mkup_trodd\" style=\"height: 53px;\">\n<td class=\"mkup_td\" style=\"width: 101.033px; height: 53px;\">oltp<\/td>\n<td class=\"mkup_td\" style=\"width: 463.167px; height: 53px;\">Transactional workloads, currently TPC-C related build and driver<\/td>\n<\/tr>\n<tr class=\"mkup_treven\" style=\"height: 53px;\">\n<td class=\"mkup_td\" style=\"width: 101.033px; height: 53px;\">opt<\/td>\n<td class=\"mkup_td\" style=\"width: 463.167px; height: 53px;\">Graphical options dialogs, takes values from database specific dict and allows modification and saving<\/td>\n<\/tr>\n<tr style=\"height: 26px;\">\n<td style=\"width: 101.033px; height: 26px;\">otc<\/td>\n<td style=\"width: 463.167px; height: 26px;\">Database specific online transaction counter<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Therefore for example in the directory \/src\/db2 the file db2opt defines the options dialogs when the db2 database is selected to load and store the dict based values. Then when a schema build is selected or driver script loaded the scripts are populated with those values entered into the dialog.<\/p>\n<h3>Virtual Users<\/h3>\n<p>Virtual Users within HammerDB are operating system threads.\u00a0 Each thread loads its own TCL interpreter and its own database interface packages.\u00a0 If you have not read the article <a href=\"https:\/\/dzone.com\/articles\/threads-done-right-with-tcl\">Threads Done Right&#8230; With Tcl<\/a> then now is a good time to do so to understand why HammerDB is so scalable.\u00a0 (Note that the metrics interface and transaction counter also run in threads).<\/p>\n<p><a href=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/threads.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-236\" src=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/threads.png\" alt=\"\" width=\"815\" height=\"676\" srcset=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/threads.png 815w, https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/threads-300x249.png 300w, https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/threads-768x637.png 768w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/a><\/p>\n<p>For example on Windows drilling down on the process explorer shows that the threads are evenly allocated to a different preferred CPU thereby making the best possible utilisation of the resources available.\u00a0 When the virtual users are run the threads are posted the script in the Script Editor in the GUI (or the loaded script for the command line). At its simplest the following is a Hello World! program in TCL.<\/p>\n<pre>#!\/usr\/local\/bin\/tclsh8.6\r\nputs \"Hello World!\"<\/pre>\n<p>Load this into the script editor and run it (or for one virtual user use the &#8220;Test TCL Code&#8221; button and the Virtual User will receive and run the program.<\/p>\n<p><a href=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/hellow.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-238\" src=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/hellow.png\" alt=\"\" width=\"815\" height=\"676\" srcset=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/hellow.png 815w, https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/hellow-300x249.png 300w, https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/11\/hellow-768x637.png 768w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/a><\/p>\n<p>Using the File -&gt; Save dialog you can modify existing scripts and then save and reload them for later use.<\/p>\n<h3>Running the Build and Driver Scripts<\/h3>\n<p>For the schema build or timed tests each virtual user receives and runs an identical copy of the script however is able to do something different. Each virtual user or operating system can identify its own thread id and therefore can be tasked with running a different part of the workload accordingly. This is how multiple virtual users will load a different part of the schema or how the virtual user that monitors a workload is identified.\u00a0 Also the threads can &#8220;talk to each other&#8221; and respond to user input such as pressing the stop button using thread shared variables.\u00a0 Otherwise overheads are minimal each virtual user will run entirely independently without interference from other threads and without locking overhead.\u00a0 Therefore running HammerDB on a multi-core and multi-threaded CPU is strongly recommended as you will be able to take advantage of that processing power.\u00a0 Output from virtual users are displayed to the virtual user output window.\u00a0 Note that operating system displays are not thread safe and cannot be updated by more than one thread at a time, therefore each virtual user sends its output to the master thread for display. Clearly a &#8220;Test Script&#8221; will not be able to generate the same level of throughput as a &#8220;Timed Script&#8221; for this reason. HammerDB also manages the virtual user status and reports any errors produced by the virtual users to the console.<\/p>\n<h3>Autopilot and Modes<\/h3>\n<p>In addition to direct interaction HammerDB also provides an autopilot feature to automate testing.\u00a0 This feature to be used in conjunction with timed tests allows for multiple tests to be run consecutively unattended without manual interaction. The way this feature works is for a timer to run at the user specified interval and at this timer interval HammerDB will automatically press the buttons that manual interaction would do. From a conceptual standpoint it is important to understand this as autopilot actually presses the same buttons that a user would, the only difference is that this is on a timed basis. Therefore if you want an autopilot run to complete successfully ensure that the time interval is long enough for your test to complete. There is no autopilot feature in the command-line tool as it is easier to script this functionality with the command-line.<\/p>\n<p>Typically HammerDB will run in Local Mode however this modes feature allows an instance of HammerDB to be created as a Master and then multiple Slave instances connected to HammerDB to be controlled by the Master through network communication. This feature has been designed for scenarios where the user wants to direct a workload specifically at multiple database instances in a cluster or in a virtualized environment.<\/p>\n<h3>Summary<\/h3>\n<p>It should now be clear that HammerDB is a simple and modular application yet extremely powerful and high performance because of the multi-threaded architecture and design. HammerDB is also highly extensible and extensions written in C can be added to support for example new databases (or existing extensions used). After this simply adding a new config file and adding these details to database.xml and creating a new directory under the src directory is all that is needed to add another database to HammerDB.\u00a0 Similarly new workloads can be added by modifying existing files. HammerDB will then take care of running these workloads either graphically or at the command line.<\/p>\n<p>Of the most importance however it should be clear that HammerDB is completely and entirely open source. TCL itself is open source, all of the database extensions are open source and the database libraries themselves with the exception of commerical databases are open-source as well.\u00a0 Also clearly all of the HammerDB code is open-source and readable within each installation so if you desire you can inspect literally every line of code right from the TCL interpreter to the extensions and HammerDB if you wish to do so.\u00a0 Therefore nothing is hidden and nothing is proprietary giving absolute confidence in the results that HammerDB produces.\u00a0 You are also empowered to modify, add and contribute improvements. HammerDB really is all about making database performance open-source and demystifying the often hidden aspects of database benchmarking from workloads to results.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>HammerDB is open source and all of the source code is available at the sourceforge Git development site here https:\/\/sourceforge.net\/p\/hammerdb\/code\/ci\/master\/tree\/ or the github mirror here https:\/\/github.com\/sm-shaw\/HammerDB.\u00a0 This Git repository is updated with every release.\u00a0 In fact all of this source code is also included in readable form with each and every release.\u00a0 However if you &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.hammerdb.com\/blog\/uncategorized\/hammerdb-concepts-and-architecture\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;HammerDB Concepts and Architecture&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"ppma_author":[5],"class_list":["post-203","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"authors":[{"term_id":5,"user_id":2,"is_guest":0,"slug":"hammerdb","display_name":"HammerDB","avatar_url":{"url":"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/10\/logo-white.png","url2x":"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/10\/logo-white.png"},"author_category":"","user_url":"http:\/\/www.hammerdb.com","last_name":"","first_name":"","job_title":"","description":""}],"_links":{"self":[{"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/posts\/203","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/comments?post=203"}],"version-history":[{"count":50,"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/posts\/203\/revisions"}],"predecessor-version":[{"id":302,"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/posts\/203\/revisions\/302"}],"wp:attachment":[{"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/media?parent=203"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/categories?post=203"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/tags?post=203"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=203"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}