From: glyn Date: Fri, 17 Jan 2014 15:56:47 +0000 (+0000) Subject: Initial project check in X-Git-Url: https://git.8kb.co.uk/?a=commitdiff_plain;h=5019ca5936e413749df9b483664bc00e5cafbd15;p=postgresql%2Fdblt Initial project check in --- diff --git a/.gitignore b/.gitignore index bdc3535..decdda8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +<<<<<<< HEAD +.DS_Store +Thumb.db +======= # Build Folders (you can keep bin if you'd like, to store dlls and pdbs) [Bb]in/ [Oo]bj/ @@ -106,3 +110,4 @@ Generated_Code #added for RIA/Silverlight projects _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML +>>>>>>> fde9f7ab6009e48ed05936471f4553afa32adf7e diff --git a/README.md b/README.md index f22e561..94ebe1f 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,85 @@ dblt ==== A C# load testing program for PostgreSQL using the npgsql data provider. + +Usage +----- + +Run parameters are specified in the *App.config* file and the sql transactions +to run are read from a separate xml file specified in the *TransactionsFile* +parameter. + +App.config parameters +--------------------- + +**ServerDescription** (text) - A description about the test run + +**PgConnectionString** (test) - The npgsql connection string + +**ConnectionRetry** (boolean) - boolean - Whether or not clients that + fail to connect should retry (true), + or give up (false) + +**ConnectionPerTransaction** (boolean) - boolean - Whether clients should + connect and disconnect for each + attempted transaction (true), or keep + their connection open (false) + +**LogFile** (text) - Path to file where verbose details + of the test run are logged + +**CsvLogFile** (text) - Path to file where statistical results + of test run are logged + +**LogLevel** (integer) - Verbosity level of log data logged into + the log file specified in the "LogFile" + parameter + (0 = minimal, 1 = standard, 2 = verbose) + +**VerboseScreen** (boolean) - Display verbose details of the test + to the screen rather than show a summary + +**Clients** (integer) - Quantity of clients to use for a single + test, set to 0 if doing multiple tests. + +**ClientsScale** (integer) - Set along with "ClientsMax" parameter + to run a set of tests with incrementing + clients + E.g. ClientsScale = 4 ClientsMax = 16 + will run 4 tests with 4,8,12 and 16 clients + +**ClientsMax** (integer) - Maximum quantiy of clients to run the test + with as detailed above + +**Iterations** (integer) - Number of iterations for each client + to run + +**SleepTime** (integer) - Time for each client to sleep between + iterations (milliseconds) + +**TransactionsFile** (text) - Xml file containing the SQL for each + iteration of the client - this can contain + multiple transactions. + +The transactions xml file contains a set of transactions and sql statements to +be executed against the database. There's nothing overly intelligent about this +file, it is simply a root node containing *\* and *\* +sub nodes, for which any can have a random attribute assigned to make them be +either run or skipped on a random basis. + +The text *#client_id#* will also be replaced with the integer id of each client +thread in the testing program; this can be usefull for identifying individual +clients against queries. + + + + SELECT 'I am client #client_id#'; + SELECT 2; + + + SELECT 'something'; + SELECT 20; + + + + diff --git a/dblt/src/dblt.sln b/dblt/src/dblt.sln new file mode 100644 index 0000000..eb906c4 --- /dev/null +++ b/dblt/src/dblt.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dblt", "dblt\dblt.csproj", "{A22A20C7-E58D-48CD-8CA4-A38117BFAE8E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A22A20C7-E58D-48CD-8CA4-A38117BFAE8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A22A20C7-E58D-48CD-8CA4-A38117BFAE8E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A22A20C7-E58D-48CD-8CA4-A38117BFAE8E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A22A20C7-E58D-48CD-8CA4-A38117BFAE8E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/dblt/src/dblt/App.config b/dblt/src/dblt/App.config new file mode 100644 index 0000000..6535a8a --- /dev/null +++ b/dblt/src/dblt/App.config @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dblt/src/dblt/Blue cube.ico b/dblt/src/dblt/Blue cube.ico new file mode 100644 index 0000000..5de1cb9 Binary files /dev/null and b/dblt/src/dblt/Blue cube.ico differ diff --git a/dblt/src/dblt/Program.cs b/dblt/src/dblt/Program.cs new file mode 100644 index 0000000..6158ec7 --- /dev/null +++ b/dblt/src/dblt/Program.cs @@ -0,0 +1,538 @@ +//Copyright (c) 2010-2011 Glyn Astill +//Copyright Notice: GPL + +using System; +using System.Collections.Generic; +using System.Xml; +using System.Text; +using System.IO; +using System.Threading; +using System.Data; +using Npgsql; +using System.Configuration; +using System.Diagnostics; + +namespace dblt +{ + class dblt + { + public static string sServerDescription = (string)ConfigurationManager.AppSettings["ServerDescription"]; + public static int iClients = Convert.ToInt32(ConfigurationManager.AppSettings["Clients"]); + public static int iClientsScale = Convert.ToInt32(ConfigurationManager.AppSettings["ClientsScale"]); + public static int iClientsMax = Convert.ToInt32(ConfigurationManager.AppSettings["ClientsMax"]); + public static int iIterations = Convert.ToInt32(ConfigurationManager.AppSettings["Iterations"]); + public static string sLogFile = (string)ConfigurationManager.AppSettings["LogFile"]; + public static string sCsvLogFile = (string)ConfigurationManager.AppSettings["CsvLogFile"]; + public static int iLogLevel = Convert.ToInt32(ConfigurationManager.AppSettings["LogLevel"]); + public static bool bVerboseScreen = Convert.ToBoolean(ConfigurationManager.AppSettings["VerboseScreen"]); + public static bool bOnFailureRetry = Convert.ToBoolean(ConfigurationManager.AppSettings["ConnectionRetry"]); + public static bool bConnPerIteration = Convert.ToBoolean(ConfigurationManager.AppSettings["ConnectionPerIteration"]); + public static string sConn = (string)ConfigurationManager.AppSettings["PgConnectionString"]; + public static string sTransactionsFile = (string)ConfigurationManager.AppSettings["TransactionsFile"]; + public static int iSleepTime = Convert.ToInt32(ConfigurationManager.AppSettings["SleepTime"]); + + public static Object oTransCounterLock = new Object(); + public static Object oIterationCounterLock = new Object(); + public static Object oTransDurationLock = new Object(); + public static Object oLogLock = new Object(); + + //public static DataSet dsTransactions = readTransactionsFile(sTransactionsFile); + public static XmlDocument xmlTransactions = readTransactionsFile(sTransactionsFile); + + + private static PerformanceCounter oCpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total"); + private static PerformanceCounter oSysCpuCounter = new PerformanceCounter("Processor", "% Privileged Time", "_Total"); + private static PerformanceCounter oUseCpuCounter = new PerformanceCounter("Processor", "% User Time", "_Total"); + + public static string timeStamp = "dd/MM/yyyy HH:mm"; + public static string[] aLogArray = new string[10000000]; + //public static double[] aTransactionTimeArray = new double[iClientsMax * iIterations * dsTransactions.Tables[0].Columns.Count]; + public static double[] aTransactionTimeArray = new double[iClientsMax * iIterations * xmlTransactions.SelectNodes("//transaction").Count]; + + public static int iLogIndex, iRunningAtMax, iRunningAtMin, iMaxRunning, iCompletedIterations, iCompletedTransactions; + public static int iCompletedQueries, iRunningClients, iRunningTransactions, iConnectionTimeouts; + public static int iConnectionCeilingHit, iConnectionFailure, iConnectionRetries, iFailure, iTransactionTimeIndex; + public static double iMaxTransDuration, iMinTransDuration; + public static bool bRunning = false; + + static void Main(string[] args) + { + if (iClients != 0) + { + MainWorker(iClients); + } + else if (iClientsScale != 0) + { + if (iClientsMax == 0) + { + iClientsMax = iClientsScale; + } + for (int i = iClientsScale; i <= iClientsMax; i= i+iClientsScale) + { + MainWorker(i); + } + } + } + + public static void MainWorker(int iClientsRun) + { + iClients = iClientsRun; + + Array.Clear(aLogArray, 0, iLogIndex); + iLogIndex = 0; + Array.Clear(aTransactionTimeArray, 0, iTransactionTimeIndex); + iTransactionTimeIndex = 0; + iMaxTransDuration = 0; + iMinTransDuration = 100000000000000000; + iRunningAtMax = 0; + iRunningAtMin = 0; + iMaxRunning = 0; + iCompletedIterations = 0; + iCompletedTransactions = 0; + iCompletedQueries = 0; + iRunningClients = 0; + iRunningTransactions = 0; + iConnectionTimeouts = 0; + iConnectionCeilingHit = 0; + iConnectionFailure = 0; + iConnectionRetries = 0; + iFailure = 0; + bRunning = false; + + Console.Clear(); + + Info("-------------------- Test Start --------------------", iLogLevel, false); + Info("Server Description: " + sServerDescription, iLogLevel, false); + Info("Database load tester.", iLogLevel, true); + Info("Iterations per client = " + iIterations, iLogLevel, true); + Info("launching " + iClients + " clients...", iLogLevel, true); + + Thread[] workerThreads = new Thread[iClients]; + + bRunning = true; + Thread infoThread = new Thread(new ThreadStart(InfoScreen)); + infoThread.Start(); + + for (int i = 0; i < workerThreads.Length; i++) + { + workerThreads[i] = new Thread(new ParameterizedThreadStart(ClientWorker)); + workerThreads[i].Start(i); + iRunningClients++; + } + + for (int i = 0; i < workerThreads.Length; i++) + { + workerThreads[i].Join(); + iRunningClients--; + } + + bRunning = false; + infoThread.Join(); + + Info("-------------------- Test Complete --------------------", iLogLevel, false); + LogWriter(); + } + + public static void InfoScreen() + { + DateTime startTime = DateTime.Now; + DateTime currTime = DateTime.Now; + TimeSpan duration = currTime - startTime; + + double iMeanTransactionDuration = 0; + double iStandatdDeviation = 0; + + float fCpuAll = 0; + float fCpuSys = 0; + float fCpuUse = 0; + int iSamples = 0; + + if (!bVerboseScreen) + { + while (bRunning) + { + fCpuAll = fCpuAll + oCpuCounter.NextValue(); + fCpuSys = fCpuSys + oSysCpuCounter.NextValue(); + fCpuUse = fCpuUse + oUseCpuCounter.NextValue(); + iSamples++; + + currTime = DateTime.Now; + duration = currTime - startTime; + + Console.SetCursorPosition(0, 4); + Console.WriteLine("Running Clients {0} ", iRunningClients); + Console.SetCursorPosition(0, 5); + Console.WriteLine("Running Transactions {0} : {1} max ", iRunningTransactions, iMaxRunning); + + Console.SetCursorPosition(0, 7); + Console.WriteLine("Completed Queries {0} : {1} qps ", iCompletedQueries, (iCompletedQueries / (Convert.ToInt32(duration.TotalSeconds) + 1))); + Console.SetCursorPosition(0, 8); + Console.WriteLine("Completed Transactions {0} : {1} tps ", iCompletedTransactions, (iCompletedTransactions / (Convert.ToInt32(duration.TotalSeconds) + 1))); + Console.SetCursorPosition(0, 9); + Console.WriteLine("Completed Iterations {0} / {1} ", iCompletedIterations, (iIterations * iClients)); + + Console.SetCursorPosition(0, 11); + Console.WriteLine("Maximum Transaction+Read Time {0} ms : {1} Running ", iMaxTransDuration, iRunningAtMax); + Console.SetCursorPosition(0, 12); + Console.WriteLine("Minimum Transaction+Read Time {0} ms : {1} Running ", iMinTransDuration, iRunningAtMin); + + Console.SetCursorPosition(0, 14); + Console.WriteLine("Connection Timeout/Ceiling Hit/Failure {0} / {1} / {2} ", iConnectionTimeouts, iConnectionCeilingHit, iConnectionFailure); + Console.SetCursorPosition(0, 15); + Console.WriteLine("Other Failure {0} ", iFailure); + Console.SetCursorPosition(0, 16); + Console.WriteLine("Connection Retries {0} ", iConnectionRetries); + Console.SetCursorPosition(0, 17); + Console.WriteLine("Average Client CPU All/User/Sys {0}% / {1}% / {2}% ", Math.Round((fCpuAll / iSamples), 2), Math.Round((fCpuUse / iSamples), 2), Math.Round((fCpuSys / iSamples), 2)); + + Console.SetCursorPosition(0, 23); + Console.WriteLine("{0} s ", (Convert.ToInt32(duration.TotalSeconds) + 1)); + Thread.Sleep(500); + } + } + + if (!bRunning) + { + Thread.Sleep(500); + + Console.SetCursorPosition(0, 4); + Console.WriteLine("Running Clients {0} ", iRunningClients); + Console.SetCursorPosition(0, 5); + Console.WriteLine("Running Transactions {0} : {1} max ", iRunningTransactions, iMaxRunning); + + Console.SetCursorPosition(0, 7); + Console.WriteLine("Completed Queries {0} : {1} qps ", iCompletedQueries, (iCompletedQueries / (Convert.ToInt32(duration.TotalSeconds) + 1))); + Console.SetCursorPosition(0, 8); + Console.WriteLine("Completed Transactions {0} : {1} tps ", iCompletedTransactions, (iCompletedTransactions / (Convert.ToInt32(duration.TotalSeconds) + 1))); + Console.SetCursorPosition(0, 9); + Console.WriteLine("Completed Iterations {0} / {1} ", iCompletedIterations, (iIterations * iClients)); + + Console.SetCursorPosition(0, 11); + Console.WriteLine("Maximum Transaction+Read Time {0} ms : {1} Running ", iMaxTransDuration, iRunningAtMax); + Console.SetCursorPosition(0, 12); + Console.WriteLine("Minimum Transaction+Read Time {0} ms : {1} Running ", iMinTransDuration, iRunningAtMin); + + Console.SetCursorPosition(0, 14); + Console.WriteLine("Connection Timeout/Ceiling Hit/Failure {0} / {1} / {2} ", iConnectionTimeouts, iConnectionCeilingHit, iConnectionFailure); + Console.SetCursorPosition(0, 15); + Console.WriteLine("Other Failure {0} ", iFailure); + Console.SetCursorPosition(0, 16); + Console.WriteLine("Connection Retries {0} ", iConnectionRetries); + Console.SetCursorPosition(0, 17); + Console.WriteLine("Average Client CPU All/User/Sys {0}% / {1}% / {2}% ", Math.Round((fCpuAll / iSamples),2), Math.Round((fCpuUse / iSamples),2), Math.Round((fCpuSys / iSamples),2)); + + Console.SetCursorPosition(0, 23); + Console.WriteLine("{0} s ", (Convert.ToInt32(duration.TotalSeconds) + 1)); + + Info("==========================================================", iLogLevel, bVerboseScreen); + Info(" Running Clients " + iRunningClients, iLogLevel, bVerboseScreen); + Info(" Running Transactions " + iRunningTransactions, iLogLevel, bVerboseScreen); + Info(" Completed Queries " + iCompletedQueries + " : " + (iCompletedQueries / (Convert.ToInt32(duration.TotalSeconds) + 1)) + " qps", iLogLevel, bVerboseScreen); + Info(" Completed Transactions " + iCompletedTransactions + " : " + (iCompletedTransactions / (Convert.ToInt32(duration.TotalSeconds) + 1)) + " tps", iLogLevel, bVerboseScreen); + Info(" Completed Iterations " + iCompletedIterations + " / " + (iIterations * iClients), iLogLevel, bVerboseScreen); + Info(" Maximum Transaction+Read Time " + iMaxTransDuration + " ms", iLogLevel, bVerboseScreen); + Info(" Minimum Transaction+Read Time " + iMinTransDuration + " ms", iLogLevel, bVerboseScreen); + Info(" Connection Timeout/Ceiling Hit/Failure " + iConnectionTimeouts + " / " + iConnectionCeilingHit + " / " + iConnectionFailure, iLogLevel, bVerboseScreen); + Info(" Other Failure " + iFailure, iLogLevel, bVerboseScreen); + Info(" Connection Retries " + iConnectionRetries, iLogLevel, bVerboseScreen); + Info(" Total Time " + Convert.ToInt32(duration.TotalSeconds) + 1, iLogLevel, bVerboseScreen); + Info(" Max Concurrent Transactions " + iMaxRunning, iLogLevel, bVerboseScreen); + Info(" Average Client CPU All/User/Sys " + Math.Round((fCpuAll / iSamples), 2) + "% " + Math.Round((fCpuUse / iSamples), 2) + "% " + Math.Round((fCpuSys / iSamples), 2) + "%", iLogLevel, bVerboseScreen); + Info("==========================================================", iLogLevel, bVerboseScreen); + + iMeanTransactionDuration = 0; + iStandatdDeviation = 0; + + for (int i = 0; i < iTransactionTimeIndex; i++) + { + iMeanTransactionDuration = (aTransactionTimeArray[i] + iMeanTransactionDuration); + } + iMeanTransactionDuration = (iMeanTransactionDuration / iTransactionTimeIndex); + + for (int i = 0; i < iTransactionTimeIndex; i++) + { + + iStandatdDeviation = (Math.Pow((aTransactionTimeArray[i] - iMeanTransactionDuration), 2) + iStandatdDeviation); + } + iStandatdDeviation = Math.Sqrt(iStandatdDeviation / iTransactionTimeIndex); + + CsvLogWriter("\"" + sServerDescription + "\"," + iClients + "," + iIterations + "," + iMaxTransDuration + "," + iMinTransDuration + "," + iRunningAtMax + "," + iRunningAtMin + "," + iMeanTransactionDuration + "," + iStandatdDeviation + "," + (iCompletedTransactions / (Convert.ToInt32(duration.TotalSeconds) + 1)) + "," + (iCompletedQueries / (Convert.ToInt32(duration.TotalSeconds) + 1)) + "," + iMaxRunning + "," + (Convert.ToInt32(duration.TotalSeconds) + 1) + "," + (fCpuAll / iSamples)); + } + } + + public static void ClientWorker(object iThread) + { + + Info("Starting client thread " + iThread.ToString(), iLogLevel, bVerboseScreen); + + Random random = new Random(); + int iTransOn = 0; + int iSqlOn = 0; + string sSql = ""; + int iRandomStmt = 0; + int iRandomTran = 0; + NpgsqlConnection conn = null; + if (!bConnPerIteration) + { + conn = new NpgsqlConnection(sConn); + conn.Open(); + } + + for (int i = 0; i < iIterations; i++) + { + try + { + DateTime startTime = DateTime.Now; + if (bConnPerIteration) + { + conn = new NpgsqlConnection(sConn); + conn.Open(); + } + + //foreach (DataRow transaction in dsTransactions.Tables[0].Rows) + iTransOn = 0; + foreach (XmlNode node in xmlTransactions.SelectNodes("//transaction")) + { + iTransOn++; + XmlNode randomtransaction = node.Attributes["random"]; + if (randomtransaction != null && node.Attributes["random"].Value.Trim().ToLower() == "true") + { + iRandomTran = random.Next(0, 2); + } + + if (iRandomTran == 0) + { + NpgsqlTransaction tran = conn.BeginTransaction(); + DateTime beginTime = DateTime.Now; + + lock (oTransCounterLock) + { + iRunningTransactions++; + } + + //foreach (DataColumn column in dsTransactions.Tables[0].Columns) + iSqlOn = 0; + foreach (XmlNode subnode in node.SelectNodes("//sql")) + { + iSqlOn++; + XmlNode randomsql = subnode.Attributes["random"]; + if (randomsql != null && subnode.Attributes["random"].Value.Trim().ToLower() == "true") + { + iRandomStmt = random.Next(0, 2); + } + + if (iRandomStmt == 0) + { + sSql = subnode.InnerText; + //NpgsqlCommand command = new NpgsqlCommand(transaction[column].ToString().Replace("#client_id#", iThread.ToString()), conn, tran); + NpgsqlCommand command = new NpgsqlCommand(sSql.Replace("#client_id#", iThread.ToString()), conn, tran); + NpgsqlDataReader dr = command.ExecuteReader(); + + iCompletedQueries++; + while (dr.Read()) + { + //Just pull the data back into our dataset (but we don't care about it) + } + + if (iLogLevel > 1) + { + Info("Client " + iThread.ToString() + " Transaction = " + iTransOn + " Statement = " + iSqlOn + " SQL = \"" + sSql + "\" Running", iLogLevel, bVerboseScreen); + } + } + else + { + if (iLogLevel > 1) + { + Info("Client " + iThread.ToString() + " Transaction = " + iTransOn + " Statement = " + iSqlOn + " Skipping as random statement = true", iLogLevel, bVerboseScreen); + } + } + } + + tran.Commit(); + DateTime commitTime = DateTime.Now; + TimeSpan transactionDuration = commitTime - beginTime; + + if (iRunningClients == iClients) + { + + if (transactionDuration.TotalMilliseconds > iMaxTransDuration) + { + lock (oTransDurationLock) + { + iMaxTransDuration = transactionDuration.TotalMilliseconds; + iRunningAtMax = iRunningTransactions; + } + } + if (transactionDuration.TotalMilliseconds < iMinTransDuration) + { + lock (oTransDurationLock) + { + iMinTransDuration = transactionDuration.TotalMilliseconds; + iRunningAtMin = iRunningTransactions; + } + } + } + lock (oTransCounterLock) + { + if (iRunningTransactions > iMaxRunning) + { + iMaxRunning = iRunningTransactions; + } + iCompletedTransactions++; + aTransactionTimeArray[iTransactionTimeIndex] = transactionDuration.TotalMilliseconds; + iTransactionTimeIndex++; + iRunningTransactions--; + } + } + else + { + if (iLogLevel > 1) + { + Info("Client " + iThread.ToString() + " Transaction = " + iTransOn + " Skipping as random transaction = true", iLogLevel, bVerboseScreen); + } + } + } + + lock (oIterationCounterLock) + { + iCompletedIterations++; + } + + if (bConnPerIteration) + { + conn.Close(); + } + + DateTime stopTime = DateTime.Now; + TimeSpan duration = stopTime - startTime; + Info("Client " + iThread.ToString() + " Iteration " + i.ToString() + " Iteration Time " + duration.TotalMilliseconds + " ms (including application read)", iLogLevel, bVerboseScreen); + + } + catch (Exception e) + { + if (String.Compare(e.Message, 0, "A timeout has occured", 0, 21) == 0) + { + iConnectionTimeouts++; + } + else if (String.Compare(e.Message, 0, "Failed to establish a connection", 0, 32) == 0) + { + iConnectionFailure++; + } + else if ((e.Message == "ERROR: 08P01: no more connections allowed") || (e.Message == "FATAL: 53300: connection limit exceeded for non-superusers") || (e.Message == "FATAL: 53300: sorry, too many clients already")) + { + iConnectionCeilingHit++; + } + else + { + iFailure++; + } + Info("Client " + iThread.ToString() + " Iteration " + i.ToString() + " FAILURE " + e.Message + " TARGET " + e.TargetSite + " INFO = " + e.ToString(), iLogLevel, bVerboseScreen); + if (bOnFailureRetry) + { + i--; + iConnectionRetries++; + continue; + } + + } + if (iSleepTime > 0) + { + Thread.Sleep(iSleepTime); + } + } + if (!bConnPerIteration) + { + conn.Close(); + } + } + + public static void Info(string sInfoText, int iInfoLevel, bool bScreen) + { + if (iInfoLevel >= 1) + { + AddLog(sInfoText); + } + if (bScreen) + { + Console.WriteLine(sInfoText); + } + } + + public static void AddLog(string sLogText) + { + DateTime currTime = DateTime.Now; + + if (sLogText.Length != 0) + { + lock (oLogLock) + { + aLogArray[iLogIndex] = currTime.ToString(timeStamp) + " : " + sLogText; + iLogIndex++; + } + } + } + + public static void LogWriter() + { + if ((sLogFile != "") && (iLogLevel >=1)) + { + FileStream fs = new FileStream(sLogFile, FileMode.OpenOrCreate, FileAccess.Write); + StreamWriter m_streamWriter = new StreamWriter(fs); + m_streamWriter.BaseStream.Seek(0, SeekOrigin.End); + + for (int i = 0; i < iLogIndex; i++) + { + m_streamWriter.WriteLine(aLogArray[i]); + } + + m_streamWriter.Flush(); + m_streamWriter.Close(); + } + } + + public static void CsvLogWriter(string sLogText) + { + bool bWriteHeader = false; + + if (sCsvLogFile != "") + { + if (!File.Exists(sCsvLogFile)) + { + bWriteHeader = true; + } + + FileStream fs = new FileStream(sCsvLogFile, FileMode.OpenOrCreate, FileAccess.Write); + StreamWriter m_streamWriter = new StreamWriter(fs); + m_streamWriter.BaseStream.Seek(0, SeekOrigin.End); + + if (bWriteHeader) + { + m_streamWriter.WriteLine("Server name, Clients, Iterations/client, Max transaction duration (ms), Min transaction duration (ms), Concurrent transactions at max duration, Concurrent transactions at min duration, Mean transaction duration (ms), Transaction duration standard deviation (ms), tps, qps, Max concurrent transactions, Total time (s), Avg CPU Time %"); + } + m_streamWriter.WriteLine(sLogText); + + m_streamWriter.Flush(); + m_streamWriter.Close(); + } + } + + //public static DataSet readTransactionsFile(string sTransactionsFile) + public static XmlDocument readTransactionsFile(string sTransactionsFile) + { + DataSet ds = new DataSet(); + XmlDocument transfile = new XmlDocument(); + try + { + //GA ds.ReadXml(sTransactionsFile, XmlReadMode.InferSchema); + transfile.Load(sTransactionsFile); + } + catch (Exception e) + { + Info("Error reading transaction file " + e.ToString(), iLogLevel, bVerboseScreen); + } + //return ds; + return transfile; + } + } + +} \ No newline at end of file diff --git a/dblt/src/dblt/Properties/AssemblyInfo.cs b/dblt/src/dblt/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9c43649 --- /dev/null +++ b/dblt/src/dblt/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("dblt")] +[assembly: AssemblyDescription("Database Load Test")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("8kb.co.uk")] +[assembly: AssemblyProduct("dblt")] +[assembly: AssemblyCopyright("Copyright © 8kb.co.uk 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("feeaf39f-1945-434c-9611-57fc670a2048")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/dblt/src/dblt/Transactions.xml b/dblt/src/dblt/Transactions.xml new file mode 100644 index 0000000..a4f62ec --- /dev/null +++ b/dblt/src/dblt/Transactions.xml @@ -0,0 +1,12 @@ + + + + + SELECT 'I am client #client_id#'; + SELECT 2; + + + SELECT 'something'; + SELECT 20; + + diff --git a/dblt/src/dblt/dblt.csproj b/dblt/src/dblt/dblt.csproj new file mode 100644 index 0000000..6737e8b --- /dev/null +++ b/dblt/src/dblt/dblt.csproj @@ -0,0 +1,123 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {A22A20C7-E58D-48CD-8CA4-A38117BFAE8E} + Exe + Properties + dblt + dblt + dblt.dblt + true + Blue cube.ico + + + + + 3.5 + v4.0 + + http://localhost/dblt/ + true + Web + true + Foreground + 7 + Days + false + false + true + http://www.8kb.co.uk + en + .NET Database Load Tester + Glyn Astill + 0 + 1.0.0.%2a + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + + False + C:\Program Files (x86)\Microsoft Visual Studio 10.0\Npgsql2.0.11.91-bin-ms.net3.5sp1\Npgsql.dll + + + + + + + + + + + + + + Designer + + + + + + Designer + PreserveNewest + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + False + .NET Framework 3.5 SP1 + false + + + + + \ No newline at end of file