From 8631a51988d84a20b6cd036c5cf007d59ebe64bc Mon Sep 17 00:00:00 2001 From: ulvii Date: Fri, 5 May 2017 17:32:09 -0700 Subject: [PATCH 01/48] Performance tests - initial commit --- .../pdo_sqlsrv/large/PDOFetchLargeBench.php | 31 +++ .../pdo_sqlsrv/regular/PDOConnectionBench.php | 14 ++ .../regular/PDOCreateDbTableProcBench.php | 30 +++ .../pdo_sqlsrv/regular/PDODeleteBench.php | 53 ++++ .../pdo_sqlsrv/regular/PDOFetchBench.php | 50 ++++ .../pdo_sqlsrv/regular/PDOInsertBench.php | 45 ++++ .../regular/PDOSelectVersionBench.php | 25 ++ .../pdo_sqlsrv/regular/PDOUpdateBench.php | 61 +++++ .../sqlsrv/large/SqlsrvFetchLargeBench.php | 31 +++ .../sqlsrv/regular/SqlsrvConnectionBench.php | 13 + .../regular/SqlsrvCreateDbTableProcBench.php | 31 +++ .../sqlsrv/regular/SqlsrvDeleteBench.php | 53 ++++ .../sqlsrv/regular/SqlsrvFetchBench.php | 53 ++++ .../sqlsrv/regular/SqlsrvInsertBench.php | 45 ++++ .../regular/SqlsrvSelectVersionBench.php | 25 ++ .../sqlsrv/regular/SqlsrvUpdateBench.php | 61 +++++ test/Performance/lib/PDOSqlsrvUtil.php | 228 ++++++++++++++++++ test/Performance/lib/SqlsrvUtil.php | 225 +++++++++++++++++ test/Performance/lib/connect.php | 8 + 19 files changed, 1082 insertions(+) create mode 100644 test/Performance/benchmark/pdo_sqlsrv/large/PDOFetchLargeBench.php create mode 100644 test/Performance/benchmark/pdo_sqlsrv/regular/PDOConnectionBench.php create mode 100644 test/Performance/benchmark/pdo_sqlsrv/regular/PDOCreateDbTableProcBench.php create mode 100644 test/Performance/benchmark/pdo_sqlsrv/regular/PDODeleteBench.php create mode 100644 test/Performance/benchmark/pdo_sqlsrv/regular/PDOFetchBench.php create mode 100644 test/Performance/benchmark/pdo_sqlsrv/regular/PDOInsertBench.php create mode 100644 test/Performance/benchmark/pdo_sqlsrv/regular/PDOSelectVersionBench.php create mode 100644 test/Performance/benchmark/pdo_sqlsrv/regular/PDOUpdateBench.php create mode 100644 test/Performance/benchmark/sqlsrv/large/SqlsrvFetchLargeBench.php create mode 100644 test/Performance/benchmark/sqlsrv/regular/SqlsrvConnectionBench.php create mode 100644 test/Performance/benchmark/sqlsrv/regular/SqlsrvCreateDbTableProcBench.php create mode 100644 test/Performance/benchmark/sqlsrv/regular/SqlsrvDeleteBench.php create mode 100644 test/Performance/benchmark/sqlsrv/regular/SqlsrvFetchBench.php create mode 100644 test/Performance/benchmark/sqlsrv/regular/SqlsrvInsertBench.php create mode 100644 test/Performance/benchmark/sqlsrv/regular/SqlsrvSelectVersionBench.php create mode 100644 test/Performance/benchmark/sqlsrv/regular/SqlsrvUpdateBench.php create mode 100644 test/Performance/lib/PDOSqlsrvUtil.php create mode 100644 test/Performance/lib/SqlsrvUtil.php create mode 100644 test/Performance/lib/connect.php diff --git a/test/Performance/benchmark/pdo_sqlsrv/large/PDOFetchLargeBench.php b/test/Performance/benchmark/pdo_sqlsrv/large/PDOFetchLargeBench.php new file mode 100644 index 00000000..b3152745 --- /dev/null +++ b/test/Performance/benchmark/pdo_sqlsrv/large/PDOFetchLargeBench.php @@ -0,0 +1,31 @@ +tableName = "LargeDB.dbo.datatypes"; + } + + public function connect(){ + $this->conn = PDOSqlsrvUtil::connect(); + } + /* + * Each iteration calls prepare, execute and fetch APIs to fetch the already populdated data + */ + public function benchFetchWithPrepare(){ + PDOSqlsrvUtil::fetchWithPrepare( $this->conn, $this->tableName ); + } + + public function disconnect(){ + PDOSqlsrvUtil::disconnect( $this->conn ); + } +} diff --git a/test/Performance/benchmark/pdo_sqlsrv/regular/PDOConnectionBench.php b/test/Performance/benchmark/pdo_sqlsrv/regular/PDOConnectionBench.php new file mode 100644 index 00000000..f6244bac --- /dev/null +++ b/test/Performance/benchmark/pdo_sqlsrv/regular/PDOConnectionBench.php @@ -0,0 +1,14 @@ + diff --git a/test/Performance/benchmark/pdo_sqlsrv/regular/PDOCreateDbTableProcBench.php b/test/Performance/benchmark/pdo_sqlsrv/regular/PDOCreateDbTableProcBench.php new file mode 100644 index 00000000..53642b6a --- /dev/null +++ b/test/Performance/benchmark/pdo_sqlsrv/regular/PDOCreateDbTableProcBench.php @@ -0,0 +1,30 @@ +conn = PDOSqlsrvUtil::connect(); + } + /* + * Each iteration creates a database, a table and a stored procedure in that database and drops the database at the end. + * Not that, execDirect function are used to execute all the queries. + */ + public function benchCreateDbTableProc(){ + $randomNum = rand(); + $databaseName = "test_db_$randomNum"; + $tableName = "test_table_$randomNum"; + $procName = "test_proc_$randomNum"; + PDOSqlsrvUtil::createDbTableProc( $this->conn, $databaseName, $tableName, $procName ); + PDOSqlsrvUtil::dropDatabase( $this->conn, $databaseName ); + } + + public function disconnect(){ + PDOSqlsrvUtil::disconnect( $this->conn ); + } +} diff --git a/test/Performance/benchmark/pdo_sqlsrv/regular/PDODeleteBench.php b/test/Performance/benchmark/pdo_sqlsrv/regular/PDODeleteBench.php new file mode 100644 index 00000000..b3eb788e --- /dev/null +++ b/test/Performance/benchmark/pdo_sqlsrv/regular/PDODeleteBench.php @@ -0,0 +1,53 @@ +tableName = "datatypes_".rand(); + } + + public function connect(){ + $this->conn = PDOSqlsrvUtil::connect(); + } + + public function createTable(){ + PDOSqlsrvUtil::createCRUDTable( $this->conn, $this->tableName ); + } + + public function generateInsertValues(){ + $this->insertValues = PDOSqlsrvUtil::generateInsertValues(); + } + + public function insertWithPrepare(){ + for( $i=0; $i<1000; $i++ ){ + PDOSqlsrvUtil::insertWithPrepare( $this->conn, $this->tableName, $this->insertValues ); + } + } + /** + * Each iteration inserts 1000 rows into the table, benchDelete deletes top row from the table 1000 times. + * Note that, every delete calls prepare and execute APIs. + */ + public function benchDelete(){ + for( $i=0; $i<1000; $i++ ){ + PDOSqlsrvUtil::deleteWithPrepare( $this->conn, $this->tableName ); + } + } + + public function dropTable(){ + PDOSqlsrvUtil::dropTable( $this->conn, $this->tableName ); + } + + public function disconnect(){ + PDOSqlsrvUtil::disconnect( $this->conn ); + } + +} diff --git a/test/Performance/benchmark/pdo_sqlsrv/regular/PDOFetchBench.php b/test/Performance/benchmark/pdo_sqlsrv/regular/PDOFetchBench.php new file mode 100644 index 00000000..e7e17b4d --- /dev/null +++ b/test/Performance/benchmark/pdo_sqlsrv/regular/PDOFetchBench.php @@ -0,0 +1,50 @@ +tableName = "datatypes_".rand(); + } + public function connect(){ + $this->conn = PDOSqlsrvUtil::connect(); + } + + public function createTable(){ + PDOSqlsrvUtil::createCRUDTable( $this->conn, $this->tableName ); + } + + public function generateInsertValues(){ + $this->insertValues = PDOSqlsrvUtil::generateInsertValues(); + } + + public function insertWithPrepare(){ + PDOSqlsrvUtil::insertWithPrepare( $this->conn, $this->tableName, $this->insertValues ); + } + + /** + * Each iteration inserts a row into the table, benchFetchWithPrepare() fetches that row 1000 times. + * Note that, every fetch calls prepare, execute and fetch APIs. + */ + public function benchFetchWithPrepare(){ + for( $i=0; $i<1000; $i++){ + PDOSqlsrvUtil::fetchWithPrepare( $this->conn, $this->tableName ); + } + } + + public function dropTable(){ + PDOSqlsrvUtil::dropTable( $this->conn, $this->tableName ); + } + + public function disconnect(){ + PDOSqlsrvUtil::disconnect( $this->conn ); + } +} diff --git a/test/Performance/benchmark/pdo_sqlsrv/regular/PDOInsertBench.php b/test/Performance/benchmark/pdo_sqlsrv/regular/PDOInsertBench.php new file mode 100644 index 00000000..73b0e191 --- /dev/null +++ b/test/Performance/benchmark/pdo_sqlsrv/regular/PDOInsertBench.php @@ -0,0 +1,45 @@ +tableName = "datatypes_".rand(); + } + public function connect(){ + $this->conn = PDOSqlsrvUtil::connect(); + } + + public function createTable(){ + PDOSqlsrvUtil::createCRUDTable( $this->conn, $this->tableName ); + } + + public function generateInsertValues(){ + $this->insertValues = PDOSqlsrvUtil::generateInsertValues(); + } + /** + * Each iteration inserts 1000 rows into the table. + * Note that, every insertion calls prepare, bindParam and execute APIs. + */ + public function benchInsertWithPrepare(){ + for ( $i=0; $i<1000; $i++){ + PDOSqlsrvUtil::insertWithPrepare( $this->conn, $this->tableName, $this->insertValues ); + } + } + + public function dropTable(){ + PDOSqlsrvUtil::dropTable( $this->conn, $this->tableName ); + } + + public function disconnect(){ + PDOSqlsrvUtil::disconnect( $this->conn ); + } +} diff --git a/test/Performance/benchmark/pdo_sqlsrv/regular/PDOSelectVersionBench.php b/test/Performance/benchmark/pdo_sqlsrv/regular/PDOSelectVersionBench.php new file mode 100644 index 00000000..10bc5a77 --- /dev/null +++ b/test/Performance/benchmark/pdo_sqlsrv/regular/PDOSelectVersionBench.php @@ -0,0 +1,25 @@ +conn = PDOSqlsrvUtil::connect(); + } + /* + * Each iteration calls execDirect API to fetch @@Version + */ + public function benchSelectVersion(){ + $version = PDOSqlsrvUtil::selectVersion( $this->conn ); + } + + public function disconnect(){ + PDOSqlsrvUtil::disconnect( $this->conn ); + } +} diff --git a/test/Performance/benchmark/pdo_sqlsrv/regular/PDOUpdateBench.php b/test/Performance/benchmark/pdo_sqlsrv/regular/PDOUpdateBench.php new file mode 100644 index 00000000..2a582f0b --- /dev/null +++ b/test/Performance/benchmark/pdo_sqlsrv/regular/PDOUpdateBench.php @@ -0,0 +1,61 @@ +tableName = "datatypes_".rand(); + } + + public function connect(){ + $this->conn = PDOSqlsrvUtil::connect(); + } + + public function createTable(){ + PDOSqlsrvUtil::createCRUDTable( $this->conn, $this->tableName ); + } + + public function generateInsertValues(){ + $this->insertValues = PDOSqlsrvUtil::generateInsertValues(); + } + + public function insertWithPrepare(){ + PDOSqlsrvUtil::insertWithPrepare( $this->conn, $this->tableName, $this->insertValues ); + } + + public function generateUpdateValues(){ + $this->updateValues = PDOSqlsrvUtil::generateUpdateValues(); + } + + public function generateUpdateParams(){ + $this->updateParams = PDOSqlsrvUtil::generateUpdateParams(); + } + /** + * Each iteration inserts a row into the table, updateWithPrepare() updates that row 1000 times. + * Note that, every update calls prepare, bindParam and execute APIs. + */ + public function benchUpdateWithPrepare(){ + for( $i=0; $i<1000; $i++ ){ + $stmt = PDOSqlsrvUtil::updateWithPrepare( $this->conn, $this->tableName, $this->updateValues, $this->updateParams ); + } + } + + public function dropTable(){ + PDOSqlsrvUtil::dropTable( $this->conn, $this->tableName ); + } + + public function disconnect(){ + PDOSqlsrvUtil::disconnect( $this->conn ); + } + +} diff --git a/test/Performance/benchmark/sqlsrv/large/SqlsrvFetchLargeBench.php b/test/Performance/benchmark/sqlsrv/large/SqlsrvFetchLargeBench.php new file mode 100644 index 00000000..f7dc79fb --- /dev/null +++ b/test/Performance/benchmark/sqlsrv/large/SqlsrvFetchLargeBench.php @@ -0,0 +1,31 @@ +tableName = "LargeDB.dbo.datatypes"; + } + + public function connect(){ + $this->conn = SqlsrvUtil::connect(); + } + /* + * Each iteration calls prepare, execute and fetch APIs to fetch the already populdated data + */ + public function benchFetchWithPrepare(){ + SqlsrvUtil::fetchWithPrepare( $this->conn, $this->tableName ); + } + + public function disconnect(){ + SqlsrvUtil::disconnect( $this->conn ); + } +} diff --git a/test/Performance/benchmark/sqlsrv/regular/SqlsrvConnectionBench.php b/test/Performance/benchmark/sqlsrv/regular/SqlsrvConnectionBench.php new file mode 100644 index 00000000..1a59f6db --- /dev/null +++ b/test/Performance/benchmark/sqlsrv/regular/SqlsrvConnectionBench.php @@ -0,0 +1,13 @@ +conn = SqlsrvUtil::connect(); + } + + /* + * Each iteration creates a database, a table and a stored procedure in that database and drops the database at the end. + * Not that, execDirect function are used to execute all the queries. + */ + public function benchCreateDbTableProc(){ + $randomNum = rand(); + $databaseName = "test_db_$randomNum"; + $tableName = "test_table_$randomNum"; + $procName = "test_proc_$randomNum"; + SqlsrvUtil::createDbTableProc( $this->conn, $databaseName, $tableName, $procName ); + SqlsrvUtil::dropDatabase( $this->conn, $databaseName ); + } + + public function disconnect(){ + SqlsrvUtil::disconnect( $this->conn ); + } +} diff --git a/test/Performance/benchmark/sqlsrv/regular/SqlsrvDeleteBench.php b/test/Performance/benchmark/sqlsrv/regular/SqlsrvDeleteBench.php new file mode 100644 index 00000000..e47070a5 --- /dev/null +++ b/test/Performance/benchmark/sqlsrv/regular/SqlsrvDeleteBench.php @@ -0,0 +1,53 @@ +tableName = "datatypes_".rand(); + } + + public function connect(){ + $this->conn = SqlsrvUtil::connect(); + } + + public function createTable(){ + SqlsrvUtil::createCRUDTable( $this->conn, $this->tableName ); + } + + public function generateInsertValues(){ + $this->insertValues = SqlsrvUtil::generateInsertValues(); + } + + public function insertWithPrepare(){ + for ( $i=0; $i<1000; $i++ ){ + SqlsrvUtil::insertWithPrepare( $this->conn, $this->tableName, $this->insertValues ); + } + } + /** + * Each iteration inserts 1000 rows into the table, benchDelete deletes top row from the table 1000 times. + * Note that, every delete calls prepare and execute APIs. + */ + public function benchDelete(){ + for( $i=0; $i<1000; $i++ ){ + SqlsrvUtil::delete( $this->conn, $this->tableName ); + } + } + + public function dropTable(){ + SqlsrvUtil::dropTable( $this->conn, $this->tableName ); + } + + public function disconnect(){ + SqlsrvUtil::disconnect( $this->conn ); + } + +} diff --git a/test/Performance/benchmark/sqlsrv/regular/SqlsrvFetchBench.php b/test/Performance/benchmark/sqlsrv/regular/SqlsrvFetchBench.php new file mode 100644 index 00000000..035903c2 --- /dev/null +++ b/test/Performance/benchmark/sqlsrv/regular/SqlsrvFetchBench.php @@ -0,0 +1,53 @@ +tableName = "datatypes_".rand(); + } + + public function connect(){ + $this->conn = SqlsrvUtil::connect(); + } + + public function createTable(){ + SqlsrvUtil::createCRUDTable( $this->conn, $this->tableName ); + } + + public function generateInsertValues(){ + $this->insertValues = SqlsrvUtil::generateInsertValues(); + } + + public function insertWithPrepare(){ + SqlsrvUtil::insertWithPrepare( $this->conn, $this->tableName, $this->insertValues ); + } + + /** + * Each iteration inserts a row into the table, benchFetchWithPrepare() fetches that row 1000 times. + * Note that, every fetch calls prepare, execute and fetch APIs. + */ + public function benchFetchWithPrepare(){ + for( $i=0; $i<1000; $i++){ + SqlsrvUtil::fetchWithPrepare( $this->conn, $this->tableName ); + } + } + + public function dropTable(){ + SqlsrvUtil::dropTable( $this->conn, $this->tableName ); + } + + public function disconnect(){ + SqlsrvUtil::disconnect( $this->conn ); + } +} diff --git a/test/Performance/benchmark/sqlsrv/regular/SqlsrvInsertBench.php b/test/Performance/benchmark/sqlsrv/regular/SqlsrvInsertBench.php new file mode 100644 index 00000000..b5959cdd --- /dev/null +++ b/test/Performance/benchmark/sqlsrv/regular/SqlsrvInsertBench.php @@ -0,0 +1,45 @@ +tableName = "datatypes_".rand(); + } + public function connect(){ + $this->conn = SqlsrvUtil::connect(); + } + + public function createTable(){ + SqlsrvUtil::createCRUDTable( $this->conn, $this->tableName ); + } + + public function generateInsertValues(){ + $this->insertValues = SqlsrvUtil::generateInsertValues(); + } + /** + * Each iteration inserts 1000 rows into the table. + * Note that, every insertion calls prepare, bindParam and execute APIs. + */ + public function benchInsertWithPrepare(){ + for( $i=0; $i<1000; $i++ ){ + SqlsrvUtil::insertWithPrepare( $this->conn, $this->tableName, $this->insertValues ); + } + } + + public function dropTable(){ + SqlsrvUtil::dropTable( $this->conn, $this->tableName ); + } + + public function disconnect(){ + SqlsrvUtil::disconnect( $this->conn ); + } +} diff --git a/test/Performance/benchmark/sqlsrv/regular/SqlsrvSelectVersionBench.php b/test/Performance/benchmark/sqlsrv/regular/SqlsrvSelectVersionBench.php new file mode 100644 index 00000000..9567a093 --- /dev/null +++ b/test/Performance/benchmark/sqlsrv/regular/SqlsrvSelectVersionBench.php @@ -0,0 +1,25 @@ +conn = SqlsrvUtil::connect(); + } + /* + * Each iteration calls execDirect API to fetch @@Version + */ + public function benchSelectVersion(){ + $version = SqlsrvUtil::selectVersion( $this->conn ); + } + + public function disconnect(){ + SqlsrvUtil::disconnect( $this->conn ); + } +} diff --git a/test/Performance/benchmark/sqlsrv/regular/SqlsrvUpdateBench.php b/test/Performance/benchmark/sqlsrv/regular/SqlsrvUpdateBench.php new file mode 100644 index 00000000..806c336a --- /dev/null +++ b/test/Performance/benchmark/sqlsrv/regular/SqlsrvUpdateBench.php @@ -0,0 +1,61 @@ +tableName = "datatypes_".rand(); + } + + public function connect(){ + $this->conn = SqlsrvUtil::connect(); + } + + public function createTable(){ + SqlsrvUtil::createCRUDTable( $this->conn, $this->tableName ); + } + + public function generateInsertValues(){ + $this->insertValues = SqlsrvUtil::generateInsertValues(); + } + + public function insertWithPrepare(){ + SqlsrvUtil::insertWithPrepare( $this->conn, $this->tableName, $this->insertValues ); + } + + public function generateUpdateValues(){ + $this->updateValues = SqlsrvUtil::generateUpdateValues(); + } + + public function generateUpdateParams(){ + $this->updateParams = SqlsrvUtil::generateUpdateParams(); + } + /** + * Each iteration inserts a row into the table, updateWithPrepare() updates that row 1000 times. + * Note that, every update calls prepare, bindParam and execute APIs. + */ + public function benchUpdateWithPrepare(){ + for( $i=0; $i<1000; $i++ ){ + $stmt = SqlsrvUtil::updateWithPrepare( $this->conn, $this->tableName, $this->updateValues, $this->updateParams ); + } + } + + public function dropTable(){ + SqlsrvUtil::dropTable( $this->conn, $this->tableName ); + } + + public function disconnect(){ + SqlsrvUtil::disconnect( $this->conn ); + } + +} diff --git a/test/Performance/lib/PDOSqlsrvUtil.php b/test/Performance/lib/PDOSqlsrvUtil.php new file mode 100644 index 00000000..bba6d845 --- /dev/null +++ b/test/Performance/lib/PDOSqlsrvUtil.php @@ -0,0 +1,228 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + return $conn; + } + catch( PDOException $e ){ + var_dump( $e ); + exit; + } + } + + public static function disconnect( $conn ){ + $conn = null; + } + + public static function selectVersion( $conn ){ + $sql = "SELECT @@Version"; + $stmt = self::query( $conn, $sql ); + return self::fetch( $stmt ); + } + + public static function createDbTableProc( $conn, $databaseName, $tableName, $procName ){ + $tableParams = "id INTEGER, name VARCHAR(32), value INTEGER, start_date DATE, time_added TIMESTAMP, set_time TIME(7)"; + $procParams = "@id INTEGER, @name VARCHAR(32)"; + $procTextBase = "SET NOCOUNT ON; SELECT id, name, value FROM $databaseName.$tableName WHERE id = @id AND name = @name"; + self::createDatabase( $conn, $databaseName ); + self::useDatabase( $conn, $databaseName ); + self::createTable( $conn, $tableName, $tableParams ); + self::createStoredProc( $conn, $procName, $procParams, $procTextBase ); + } + + public static function generateInsertValues(){ + $vcharVal = "test string"; + $nvcharVal = "wstring"; + $intVal = 3; + $dateTimeVal = '2016-10-31 01:39:39.7341976'; + $charVal = "fixedstr"; + $ncharVal = "fixed w string"; + $realVal = 14.2; + $binVal = 0x0123456789ABCDE; + $vbinVal = 13; + $dateTimeOffsetVal = '7032-12-17 02:32:18.5210310+00:00'; + $values = array( $vcharVal, $nvcharVal, $intVal, $dateTimeVal, $charVal, $ncharVal, $realVal, $binVal, $vbinVal, $dateTimeOffsetVal ); + return $values; + } + + public static function generateUpdateValues(){ + $vcharVal = "test string updated"; + $nvcharVal = "wstring updated"; + $intVal = 5; + $dateTimeVal = '2005-10-31 01:20:39.7341976'; + $charVal = "fixedstr updated"; + $ncharVal = "fixed w string updated"; + $realVal = 19.2; + $binVal = 0x01345789ABCDE; + $vbinVal = 18; + $dateTimeOffsetVal = '1032-12-17 02:42:18.5210310+00:00'; + $updatedValues = array( $vcharVal, $nvcharVal, $intVal, $dateTimeVal, $charVal, $ncharVal, $realVal, $binVal, $vbinVal, $dateTimeOffsetVal ); + return $updatedValues; + } + + public static function generateUpdateParams(){ + $fieldNames = array( + "vstring", + "nvstring", + "num", + "dttwo", + "string", + "nstring", + "real", + "bin", + "vbin", + "dtoffset"); + + $params = ""; + foreach( $fieldNames as $fieldName ){ + $params = $params.$fieldName."=?,"; + } + $params = rtrim($params,", "); + return $params; + } + + public static function insertWithPrepare( $conn, $tableName, $values ){ + $sql = "INSERT INTO $tableName VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + $stmt = self::prepare( $conn, $sql ); + self::bindParams( $stmt, $values ); + self::execute( $stmt ); + } + + public static function fetchWithPrepare( $conn, $tableName ){ + $sql = "SELECT * FROM $tableName"; + $stmt = self::prepare( $conn, $sql ); + self::execute( $stmt ); + while ( $row = self::fetch( $stmt )){} + } + + public static function deleteWithPrepare( $conn, $tableName ){ + $sql = "DELETE TOP (1) FROM $tableName"; + $stmt = self::prepare( $conn, $sql ); + self::execute( $stmt ); + } + + public static function updateWithPrepare( $conn, $tableName, $updateValues, $params ){ + $sql = "UPDATE $tableName SET ".$params; + $stmt = self::prepare( $conn, $sql ); + self::bindParams( $stmt, $updateValues ); + self::execute( $stmt ); + } + + private function bindParams( $stmt, $values ){ + //This functionn assumes the fields are from createCRUDTable() + self::bindParam( $stmt, 1, $values[0], PDO::PARAM_STR); + self::bindParam( $stmt, 2, $values[1], PDO::PARAM_STR); + self::bindParam( $stmt, 3, $values[2], PDO::PARAM_INT); + self::bindParam( $stmt, 4, $values[3], PDO::PARAM_STR); + self::bindParam( $stmt, 5, $values[4], PDO::PARAM_STR); + self::bindParam( $stmt, 6, $values[5], PDO::PARAM_STR); + self::bindParam( $stmt, 7, $values[6], PDO::PARAM_STR); + self::bindParam( $stmt, 8, $values[7], PDO::PARAM_LOB); + self::bindParam( $stmt, 9, $values[8], PDO::PARAM_LOB); + self::bindParam( $stmt, 10, $values[9], PDO::PARAM_STR); + } + + public static function createCRUDTable( $conn, $tableName ){ + $fields = array( + "vstring" => "VARCHAR(64)", + "nvstring" => "NVARCHAR(64)", + "num" => "int", + "dttwo" => "DATETIME2", + "string" => "CHAR(64)", + "nstring" => "NCHAR(64)", + "real" => "NUMERIC", + "bin" => "BINARY(16)", + "vbin" => "VARBINARY", + "dtoffset" => "DATETIMEOFFSET"); + $params = ""; + foreach( $fields as $fieldName => $type ){ + $params .= $fieldName." ".$type.","; + } + $params = rtrim($params,", "); + self::createTable( $conn, $tableName, $params ); + } + + private function createDatabase( $conn, $dbName ){ + $sql = "CREATE DATABASE $dbName"; + self::query( $conn, $sql ); + } + + public static function dropDatabase( $conn, $dbName ){ + $sql = "USE MASTER;DROP DATABASE $dbName"; + self::query( $conn, $sql ); + } + + public static function createTable( $conn, $tableName, $params ){ + $sql = "CREATE TABLE $tableName ($params)"; + self::query( $conn, $sql ); + } + + public static function dropTable( $conn, $tableName ){ + $sql = "DROP TABLE $tableName"; + self::query( $conn, $sql ); + } + + private function useDatabase( $conn, $dbName ){ + $sql = "USE $dbName"; + self::query( $conn, $sql ); + } + + private function createStoredProc( $conn, $procName, $params, $text ){ + $sql = "CREATE PROCEDURE $procName $params AS $text"; + self::query( $conn, $sql ); + } + + private function dropStoredProc( $conn, $procName ){ + $sql = "DROP PROCEDURE $procName"; + self::query( $conn, $sql ); + } + + private function query( $conn, $sql ){ + try{ + return $conn->query( $sql ); + } + catch( PDOException $e ){ + var_dump( $e ); + exit; + } + } + + private function fetch( $stmt ){ + return $stmt->fetch(); + } + + private function prepare( $conn, $sql ){ + try{ + $stmt = $conn->prepare( $sql ); + if( $stmt === false ){ + die( "Failed to prepare\n"); + } + return $stmt; + } + catch( PDOException $e ){ + var_dump( $e ); + exit; + } + } + + private function execute( $stmt ){ + $ret = $stmt->execute(); + if( $ret === false ){ + die( "Failed to execute\n" ); + } + } + + private function bindParam( $stmt, $index, $value, $type ){ + $ret = $stmt->bindParam( $index, $value, $type ); + if ( $ret === false){ + die( "Faild to bind\n"); + } + } +} diff --git a/test/Performance/lib/SqlsrvUtil.php b/test/Performance/lib/SqlsrvUtil.php new file mode 100644 index 00000000..e80fe8ca --- /dev/null +++ b/test/Performance/lib/SqlsrvUtil.php @@ -0,0 +1,225 @@ +$database, "UID"=>$uid, "PWD"=>$pwd, "ConnectionPooling"=>$pooling, "MultipleActiveResultSets"=>$mars ); + $conn = sqlsrv_connect( $server, $options ); + if ( $conn === false ){ + die( print_r( sqlsrv_errors(), true)); + } + return $conn; + } + + public static function disconnect( $conn ){ + if ( $conn === false || $conn === null ){ + die( print_r( "Invalid connection resource\n")); + } + sqlsrv_close( $conn ); + } + + public static function selectVersion( $conn ){ + $sql = "SELECT @@Version"; + $stmt = self::query( $conn, $sql ); + self::fetch( $stmt ); + return self::getField( $stmt, 0 ); + } + + public static function createDbTableProc( $conn, $databaseName, $tableName, $procName ){ + $tableParams = "id INTEGER, name VARCHAR(32), value INTEGER, start_date DATE, time_added TIMESTAMP, set_time TIME(7)"; + $procParams = "@id INTEGER, @name VARCHAR(32)"; + $procTextBase = "SET NOCOUNT ON; SELECT id, name, value FROM $databaseName.$tableName WHERE id = @id AND name = @name"; + self::createDatabase( $conn, $databaseName ); + self::useDatabase( $conn, $databaseName ); + self::createTable( $conn, $tableName, $tableParams ); + self::createStoredProc( $conn, $procName, $procParams, $procTextBase ); + } + + public static function generateInsertValues(){ + $vcharVal = "test string"; + $nvcharVal = "wstring"; + $intVal = 3; + $dateTimeVal = '2016-10-31 01:39:39.7341976'; + $charVal = "fixedstr"; + $ncharVal = "fixed w string"; + $realVal = 14.2; + $binVal = 0x0123456789ABCDE; + $vbinVal = 13; + $dateTimeOffsetVal = '7032-12-17 02:32:18.5210310+00:00'; + $values = array( $vcharVal, $nvcharVal, $intVal, $dateTimeVal, $charVal, $ncharVal, $realVal, $binVal, $vbinVal, $dateTimeOffsetVal ); + return $values; + } + + public static function generateUpdateValues(){ + $vcharVal = "test string updated"; + $nvcharVal = "wstring updated"; + $intVal = 5; + $dateTimeVal = '2005-10-31 01:20:39.7341976'; + $charVal = "fixedstr updated"; + $ncharVal = "fixed w string updated"; + $realVal = 19.2; + $binVal = 0x01345789ABCDE; + $vbinVal = 18; + $dateTimeOffsetVal = '1032-12-17 02:42:18.5210310+00:00'; + $updatedValues = array( $vcharVal, $nvcharVal, $intVal, $dateTimeVal, $charVal, $ncharVal, $realVal, $binVal, $vbinVal, $dateTimeOffsetVal ); + return $updatedValues; + } + + public static function generateUpdateParams(){ + $fieldNames = array( + "vstring", + "nvstring", + "num", + "dttwo", + "string", + "nstring", + "real", + "bin", + "vbin", + "dtoffset"); + + $params = ""; + foreach( $fieldNames as $fieldName ){ + $params = $params.$fieldName."=?,"; + } + $params = rtrim($params,", "); + return $params; + } + + public static function insertWithPrepare( $conn, $tableName, $values ){ + $sql = "INSERT INTO $tableName VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + $stmt = self::prepare( $conn, $sql, $values ); + self::execute( $stmt ); + } + + public static function updateWithPrepare( $conn, $tableName, $updateValues, $params ){ + $sql = "UPDATE $tableName SET ".$params; + $stmt = self::prepare( $conn, $sql, $updateValues ); + self::execute( $stmt ); + } + + public static function fetchWithPrepare( $conn, $tableName ){ + $sql = "SELECT * FROM $tableName"; + $stmt = self::prepare( $conn, $sql, array()); + self::execute( $stmt ); + while ( self::fetch( $stmt )){ + for ( $i=0; $i<10; $i++ ){ + self::getField( $stmt, $i ); + } + } + } + + public static function createCRUDTable( $conn, $tableName ){ + $fields = array( + "vstring" => "VARCHAR(64)", + "nvstring" => "NVARCHAR(64)", + "num" => "int", + "dttwo" => "DATETIME2", + "string" => "CHAR(64)", + "nstring" => "NCHAR(64)", + "real" => "NUMERIC", + "bin" => "BINARY(16)", + "vbin" => "VARBINARY", + "dtoffset" => "DATETIMEOFFSET"); + $params = ""; + foreach( $fields as $fieldName => $type ){ + $params .= $fieldName." ".$type.","; + } + $params = rtrim($params,", "); + self::createTable( $conn, $tableName, $params ); + } + + public static function query( $conn, $sql ){ + $stmt = sqlsrv_query( $conn, $sql ); + if( $stmt === false ){ + die( print_r( sqlsrv_errors(), true)); + } + return $stmt; + } + + public static function fetch( $stmt ){ + $ret = sqlsrv_fetch( $stmt ); + if( $ret === false ){ + die( print_r( sqlsrv_errors(), true)); + } + return $ret; + } + + public static function getField( $stmt, $index ){ + return sqlsrv_get_field( $stmt, $index ); + } + + private function createDatabase( $conn, $dbName ){ + $sql = "CREATE DATABASE $dbName"; + self::query( $conn, $sql ); + } + + public static function dropDatabase( $conn, $dbName ){ + $sql = "USE MASTER;DROP DATABASE $dbName"; + self::query( $conn, $sql ); + } + + public static function createTable( $conn, $tableName, $params ){ + $sql = "CREATE TABLE $tableName ($params)"; + self::query( $conn, $sql ); + } + + public static function dropTable( $conn, $tableName ){ + $sql = "DROP TABLE $tableName"; + self::query( $conn, $sql ); + } + + private function useDatabase( $conn, $dbName ){ + $sql = "USE $dbName"; + self::query( $conn, $sql ); + } + + private function createStoredProc( $conn, $procName, $params, $text ){ + $sql = "CREATE PROCEDURE $procName $params AS $text"; + self::query( $conn, $sql ); + } + + private function dropStoredProc( $conn, $procName ){ + $sql = "DROP PROCEDURE $procName"; + self::query( $conn, $sql ); + } + + private function insert( $conn, $tableName, $values ){ + $sql = "INSERT INTO $tableName values ($values)"; + self::query( $conn, $sql ); + } + + private function update( $conn, $tableName, $params, $condition ){ + $sql = "UPDATE $tableName SET $params WHERE $condition"; + self::query( $sql ); + } + + public function delete( $conn, $tableName){ + $sql = "DELETE TOP (1) FROM $tableName"; + self::query( $conn, $sql ); + } + + public function deleteWithPrepare( $conn, $tableName ){ + $sql = "DELETE TOP (1) FROM $tableName"; + $stmt = self::prepare( $conn, $sql, array() ); + self::execute( $stmt ); + } + + private function prepare( $conn, $sql, $params ){ + $stmt = sqlsrv_prepare( $conn, $sql, $params ); + if( $stmt === false ){ + die( print_r( sqlsrv_errors(), true)); + } + return $stmt; + } + + public function execute( $stmt ){ + $ret = sqlsrv_execute( $stmt ); + if ( $ret === false ){ + die( print_r( sqlsrv_errors(), true)); + } + } +} diff --git a/test/Performance/lib/connect.php b/test/Performance/lib/connect.php new file mode 100644 index 00000000..a63da87b --- /dev/null +++ b/test/Performance/lib/connect.php @@ -0,0 +1,8 @@ + From 5c8038c5ae0de5337d241b480ce2b170c6cf21bc Mon Sep 17 00:00:00 2001 From: ulvii Date: Fri, 5 May 2017 17:56:32 -0700 Subject: [PATCH 02/48] Update --- test/Performance/lib/connect.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Performance/lib/connect.php b/test/Performance/lib/connect.php index a63da87b..a35108c1 100644 --- a/test/Performance/lib/connect.php +++ b/test/Performance/lib/connect.php @@ -1,8 +1,8 @@ From bc8378141aee8af4d7961ef2d65942959dccf8bd Mon Sep 17 00:00:00 2001 From: ulvii Date: Mon, 8 May 2017 10:54:56 -0700 Subject: [PATCH 03/48] Adding documentation for Performance tests --- test/Performance/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/Performance/README.md diff --git a/test/Performance/README.md b/test/Performance/README.md new file mode 100644 index 00000000..e69de29b From 88a9563e8a8a52c61befa91e0ba388b4a4289b6b Mon Sep 17 00:00:00 2001 From: ulvii Date: Thu, 18 May 2017 18:17:00 -0700 Subject: [PATCH 04/48] Initial commit for documentation --- test/Performance/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/Performance/README.md b/test/Performance/README.md index e69de29b..2bb59944 100644 --- a/test/Performance/README.md +++ b/test/Performance/README.md @@ -0,0 +1,18 @@ +Navigate into Performance folder. + +## Install Composer - Dependency Manager for PHP +https://getcomposer.org/ + +### Windows +Download and run Composer-Setup.exe https://getcomposer.org/Composer-Setup.exe + +### UNIX + + php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" + php -r "if (hash_file('SHA384', 'composer-setup.php') === '669656bab3166a7aff8a7506b8cb2d1c292f042046c5a994c43155c0be6190fa0355160742ab2e1c88d40d5be660b410') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" + php composer-setup.php + php -r "unlink('composer-setup.php');" + +## Install PHPBench + + composer require phpbench/phpbench @dev --dev From 797e76303cf366d351f29aa62dfde66b049ad753 Mon Sep 17 00:00:00 2001 From: ulvii Date: Tue, 23 May 2017 12:01:16 -0700 Subject: [PATCH 05/48] Update README.md Adding instructions how to run benchmarks --- test/Performance/README.md | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/test/Performance/README.md b/test/Performance/README.md index 2bb59944..83f0ba87 100644 --- a/test/Performance/README.md +++ b/test/Performance/README.md @@ -1,6 +1,4 @@ -Navigate into Performance folder. - -## Install Composer - Dependency Manager for PHP +## 1. Install Composer - Dependency Manager for PHP https://getcomposer.org/ ### Windows @@ -13,6 +11,30 @@ Download and run Composer-Setup.exe https://getcomposer.org/Composer-Setup.exe php composer-setup.php php -r "unlink('composer-setup.php');" -## Install PHPBench +## 2. Install PHPBench + +Navigate into Performance folder. Create the following `composer.json` file within it: + + { + "name": "Benchmark - PHP Drivers for SQL Server", + "require-dev": { + "phpbench/phpbench": "^1.0@dev" + }, + "autoload": { + "psr-4": { + "SqlsrvPerfTest\\": "lib", + "PDOSqlsrvPerfTest\\": "lib" + } + } + } + +Create `phpbench.json` in the same folder. + + { + "bootstrap": "vendor/autoload.php" + } + +## 3. Run benchmarks + + ./vendor/bin/phpbench run benchmark/ --time-unit="milliseconds" --report=aggregate - composer require phpbench/phpbench @dev --dev From c2ef4d86585ee59b01fb4863b078751ab542fb0a Mon Sep 17 00:00:00 2001 From: ulvii Date: Tue, 23 May 2017 12:43:18 -0700 Subject: [PATCH 06/48] Update README.md --- test/Performance/README.md | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/test/Performance/README.md b/test/Performance/README.md index 83f0ba87..c5c251d9 100644 --- a/test/Performance/README.md +++ b/test/Performance/README.md @@ -13,26 +13,7 @@ Download and run Composer-Setup.exe https://getcomposer.org/Composer-Setup.exe ## 2. Install PHPBench -Navigate into Performance folder. Create the following `composer.json` file within it: - - { - "name": "Benchmark - PHP Drivers for SQL Server", - "require-dev": { - "phpbench/phpbench": "^1.0@dev" - }, - "autoload": { - "psr-4": { - "SqlsrvPerfTest\\": "lib", - "PDOSqlsrvPerfTest\\": "lib" - } - } - } - -Create `phpbench.json` in the same folder. - - { - "bootstrap": "vendor/autoload.php" - } + composer install ## 3. Run benchmarks From 4fdbf63ee8ef979487069e771ec3c013ee52dacc Mon Sep 17 00:00:00 2001 From: ulvii Date: Tue, 23 May 2017 12:44:09 -0700 Subject: [PATCH 07/48] Adding json install files --- test/Performance/composer.json | 12 ++++++++++++ test/Performance/phpbench.json | 3 +++ 2 files changed, 15 insertions(+) create mode 100644 test/Performance/composer.json create mode 100644 test/Performance/phpbench.json diff --git a/test/Performance/composer.json b/test/Performance/composer.json new file mode 100644 index 00000000..891ba4f4 --- /dev/null +++ b/test/Performance/composer.json @@ -0,0 +1,12 @@ +{ + "name": "Benchmark - PHP Drivers for SQL Server", + "require-dev": { + "phpbench/phpbench": "^1.0@dev" + }, + "autoload": { + "psr-4": { + "SqlsrvPerfTest\\": "lib", + "PDOSqlsrvPerfTest\\": "lib" + } + } +} \ No newline at end of file diff --git a/test/Performance/phpbench.json b/test/Performance/phpbench.json new file mode 100644 index 00000000..6336a912 --- /dev/null +++ b/test/Performance/phpbench.json @@ -0,0 +1,3 @@ +{ + "bootstrap": "vendor/autoload.php" +} \ No newline at end of file From faf14547a29474b5a9be4de8138a600ad653cd86 Mon Sep 17 00:00:00 2001 From: ulvii Date: Tue, 23 May 2017 13:57:10 -0700 Subject: [PATCH 08/48] Update README.md Adding a few more instructions to run the benchmarks --- test/Performance/README.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/test/Performance/README.md b/test/Performance/README.md index c5c251d9..739e0d1d 100644 --- a/test/Performance/README.md +++ b/test/Performance/README.md @@ -10,12 +10,28 @@ Download and run Composer-Setup.exe https://getcomposer.org/Composer-Setup.exe php -r "if (hash_file('SHA384', 'composer-setup.php') === '669656bab3166a7aff8a7506b8cb2d1c292f042046c5a994c43155c0be6190fa0355160742ab2e1c88d40d5be660b410') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" php composer-setup.php php -r "unlink('composer-setup.php');" + mv composer.phar /usr/local/bin/composer -## 2. Install PHPBench +## 2. Install PHPBench - A Benchmark Runner for PHP +http://phpbench.readthedocs.io/en/latest/ + +Make sure git is installed and in your PATH env. Navigate into Performance folder and run: composer install ## 3. Run benchmarks - ./vendor/bin/phpbench run benchmark/ --time-unit="milliseconds" --report=aggregate +PHPBench will use the default PHP in PATH env. To specify a different PHP binary, use `--php-binary path_to_php`. Make sure `sqlsrv` and `pdo_sqlsrv` are loaded. Edit `lib/connect.php` with connection credentials. Run benchmarks. + +Run sqlsrv benchmarks: + + ./vendor/bin/phpbench run benchmark/sqlsrv/regular --time-unit="milliseconds" --iterations [num_of_iterations] --report=aggregate +Run pdo_sqlsrv benchmarks: + + ./vendor/bin/phpbench run benchmark/pdo_sqlsrv/regular --time-unit="milliseconds" --iterations [num_of_iterations] --report=aggregate + +Run benchmarks that fetch large dataset. These benchmarks assume the database is already populated with data. + + ./vendor/bin/phpbench run benchmark/sqlsrv/large --time-unit="milliseconds" --report=aggregate + ./vendor/bin/phpbench run benchmark/pdo_sqlsrv/large --time-unit="milliseconds" --report=aggregate From ac7683730087c262be5c3e2cfd3a6316669530e6 Mon Sep 17 00:00:00 2001 From: ulvii Date: Tue, 23 May 2017 15:34:41 -0700 Subject: [PATCH 09/48] Update README.md --- test/Performance/README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/Performance/README.md b/test/Performance/README.md index 739e0d1d..8b11445d 100644 --- a/test/Performance/README.md +++ b/test/Performance/README.md @@ -1,16 +1,10 @@ ## 1. Install Composer - Dependency Manager for PHP https://getcomposer.org/ -### Windows -Download and run Composer-Setup.exe https://getcomposer.org/Composer-Setup.exe - -### UNIX - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" php -r "if (hash_file('SHA384', 'composer-setup.php') === '669656bab3166a7aff8a7506b8cb2d1c292f042046c5a994c43155c0be6190fa0355160742ab2e1c88d40d5be660b410') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" php composer-setup.php php -r "unlink('composer-setup.php');" - mv composer.phar /usr/local/bin/composer ## 2. Install PHPBench - A Benchmark Runner for PHP http://phpbench.readthedocs.io/en/latest/ From 69277047bf55147c53d9de082415e5c5d5c1e317 Mon Sep 17 00:00:00 2001 From: ulvii Date: Tue, 23 May 2017 17:52:03 -0700 Subject: [PATCH 10/48] Initial commit for automation script to set up the environment and run the tests --- test/Performance/download_composer_setup.php | 4 +++ test/Performance/run-perf_tests.py | 32 ++++++++++++++++++++ test/Performance/unlink_composer_setup.php | 3 ++ 3 files changed, 39 insertions(+) create mode 100644 test/Performance/download_composer_setup.php create mode 100644 test/Performance/run-perf_tests.py create mode 100644 test/Performance/unlink_composer_setup.php diff --git a/test/Performance/download_composer_setup.php b/test/Performance/download_composer_setup.php new file mode 100644 index 00000000..aa78db56 --- /dev/null +++ b/test/Performance/download_composer_setup.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/test/Performance/run-perf_tests.py b/test/Performance/run-perf_tests.py new file mode 100644 index 00000000..b6776f24 --- /dev/null +++ b/test/Performance/run-perf_tests.py @@ -0,0 +1,32 @@ +import shutil +import os +import sys + +def check_exe(name): + path_to_exe = shutil.which(name) + if path_to_exe is not None: + print(name + " found: " + path_to_exe) + else: + sys.exit(name + " not found. Exiting...") + + +print("Checking requirements...\n") + +check_exe("php") + +print("\nPHP INFO:\n") +os.system("php -v") + +print("\nChecking if sqlsrv and pdo_sqslrv are loaded...\n") +if os.system("php --ri sqlsrv") != 0: + sys.exit("Exiting...") +if os.system("php --ri pdo_sqlsrv") != 0: + sys.exit("Exiting...") + +print("Installing Composer...") +os.system("php download_composer_setup.php") +os.system("php composer-setup.php") +os.system("php unlink_composer_setup.php") + +print("Installing PHPBench...") +os.system("php composer.phar install") \ No newline at end of file diff --git a/test/Performance/unlink_composer_setup.php b/test/Performance/unlink_composer_setup.php new file mode 100644 index 00000000..4825f35e --- /dev/null +++ b/test/Performance/unlink_composer_setup.php @@ -0,0 +1,3 @@ + \ No newline at end of file From 979933244e02a921e9b1cce58d1f6b04a91f45ef Mon Sep 17 00:00:00 2001 From: ulvii Date: Mon, 29 May 2017 18:16:57 -0700 Subject: [PATCH 11/48] Adding a script to setup Performance environment on Unix machines --- test/Performance/download_composer_setup.php | 4 - test/Performance/setup_env_unix.sh | 113 +++++++++++++++++++ test/Performance/unlink_composer_setup.php | 3 - 3 files changed, 113 insertions(+), 7 deletions(-) delete mode 100644 test/Performance/download_composer_setup.php create mode 100644 test/Performance/setup_env_unix.sh delete mode 100644 test/Performance/unlink_composer_setup.php diff --git a/test/Performance/download_composer_setup.php b/test/Performance/download_composer_setup.php deleted file mode 100644 index aa78db56..00000000 --- a/test/Performance/download_composer_setup.php +++ /dev/null @@ -1,4 +0,0 @@ - \ No newline at end of file diff --git a/test/Performance/setup_env_unix.sh b/test/Performance/setup_env_unix.sh new file mode 100644 index 00000000..bc439022 --- /dev/null +++ b/test/Performance/setup_env_unix.sh @@ -0,0 +1,113 @@ +#!/bin/bash +set -e +if [[ ("$1" = "Ubuntu16" || "$1" = "RedHat7" || "$1" = "Sierra") ]]; then + PLATFORM=$1 +else + echo "First argument must be one of Ubuntu16, RedHat7, Sierra. Exiting..." + exit 1 +fi +if [[ "$2" = "" ]]; then + echo "Second argument must be PHP version in format of 7.x.x.Exiting..." + exit +else + PHP_VERSION=$2 +fi +if [[ ("$3" != "nts" && "$3" != "ts") ]]; then + echo "Thrid argument must be either nts or ts. Exiting..." + exit 1 +else + PHP_THREAD=$3 +fi +if [[ (! -d "$4") || (! -d $4/sqlsrv) || (! -d $4/pdo_sqlsrv) || (! -d $4/shared) ]]; then + echo "Fourth argument must be path to source folder.Path not found.Exiting..." + exit 1 +else + DRIVER_SOURCE_PATH=$4 +fi +rm -rf env_setup.log +touch env_setup.log +if [ $PLATFORM = "Ubuntu16" ]; then + echo "Installing git, libxml, autoconf, openssl..." + yes | sudo apt-get install git autoconf libxml2-dev libssl-dev pkg-config >> env_setup.log 2>&1 + + echo "OK" + echo "Installing MSODBCSQL..." + curl -s https://packages.microsoft.com/keys/microsoft.asc | apt-key add - + curl -s https://packages.microsoft.com/config/ubuntu/16.04/prod.list > /etc/apt/sources.list.d/mssql-release.list + yes | sudo apt-get update >> env_setup.log 2>&1 + yes | sudo ACCEPT_EULA=Y apt-get install msodbcsql >> env_setup.log 2>&1 + yes | sudo apt-get install -qq unixodbc-dev >> env_setup.log 2>&1 +elif [ $PLATFORM = "RedHat7" ]; then + echo "Installing gcc, git, libxml, openssl..." + yes | sudo yum install -y gcc-c++ libxml2-devel git openssl-devel >> env_setup.log 2>&1 + echo "OK" + echo "Installing MSODBCSQL..." + curl -s https://packages.microsoft.com/config/rhel/7/prod.repo > /etc/yum.repos.d/mssql-release.repo + (yes | sudo ACCEPT_EULA=Y yum install -y msodbcsql >> env_setup.log 2>&1) + (yes | sudo yum install -y unixODBC-devel autoconf >> env_setup.log 2>&1) + echo "OK" +elif [ $PLATFORM = "Sierra" ]; then + echo "Installing homebrew..." + yes | /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" >> env_setup.log 2>&1 + echo "OK" + echo "Installing wget..." + #brew install wget >> env_setup.log 2>&1 + echo "OK" + + echo "Installing openssl..." + brew install pkg-config >> env_setup.log 2>&1 + brew install openssl >> env_setup.log 2>&1 + echo "OK" + echo "Installing MSODBCSQL..." + brew tap microsoft/msodbcsql https://github.com/Microsoft/homebrew-msodbcsql >> env_setup.log 2>&1 + brew update >> env_setup.log 2>&1 + yes | ACCEPT_EULA=Y brew install msodbcsql >> env_setup.log 2>&1 + echo "OK" + yes | brew install autoconf >> env_setup.log 2>&1 +fi +echo "Downloading PHP-$PHP_VERSION source tarball..." +wget http://ca1.php.net/get/php-$PHP_VERSION.tar.gz/from/this/mirror -O php-$PHP_VERSION.tar.gz >> env_setup.log 2>&1 +echo "OK" +echo "Extracting PHP source tarball..." +rm -rf php-$PHP_VERSION +tar -xf php-$PHP_VERSION.tar.gz +echo "OK" +cd php-$PHP_VERSION +mkdir ext/sqlsrv ext/pdo_sqlsrv +cp -r $DRIVER_SOURCE_PATH/sqlsrv/* $DRIVER_SOURCE_PATH/shared ext/sqlsrv +cp -r $DRIVER_SOURCE_PATH/pdo_sqlsrv/* $DRIVER_SOURCE_PATH/shared ext/pdo_sqlsrv +./buildconf --force >> ../env_setup.log 2>&1 +CONFIG_OPTIONS="--enable-cli --enable-cgi --enable-pdo --enable-sqlsrv=shared --with-pdo_sqlsrv=shared --with-odbcver=0x0380 --with-zlib --enable-mbstring --prefix=/usr/local" +[ "${PHP_THREAD}" == "ts" ] && CONFIG_OPTIONS=${CONFIG_OPTIONS}" --enable-maintainer-zts" +if [ $PLATFORM = "Sierra" ]; then + CONFIG_OPTIONS=$CONFIG_OPTIONS" --with-openssl=/usr/local/opt/openssl/" +else + CONFIG_OPTIONS=$CONFIG_OPTIONS" --with-openssl" +fi +echo "Configuring PHP..." +(./configure $CONFIG_OPTIONS >> ../env_setup.log 2>&1) +echo "OK" +echo "Compiling PHP and the drivers..." +make >> ../env_setup.log 2>&1 +echo "OK" +sudo make install >> ../env_setup.log 2>&1 +cp php.ini-production php.ini +EXTENSION_DIR=`php-config --extension-dir` +echo "extension=$EXTENSION_DIR/sqlsrv.so" >> php.ini +echo "extension=$EXTENSION_DIR/pdo_sqlsrv.so" >> php.ini +sudo cp php.ini /usr/local/lib +cd .. +php -v +php --ri sqlsrv +php --ri pdo_sqlsrv +echo "Installing Composer..." +wget https://getcomposer.org/installer -O composer-setup.php >> env_setup.log 2>&1 +php composer-setup.php >> env_setup.log 2>&1 +echo "OK" +echo "Installing PHPBench..." +php composer.phar install >> env_setup.log 2>&1 +echo "OK" +echo "Cleaning up..." +rm -rf php-$PHP_VERSION* compser-setup.php +echo "OK" +echo "Setup completed!" \ No newline at end of file diff --git a/test/Performance/unlink_composer_setup.php b/test/Performance/unlink_composer_setup.php deleted file mode 100644 index 4825f35e..00000000 --- a/test/Performance/unlink_composer_setup.php +++ /dev/null @@ -1,3 +0,0 @@ - \ No newline at end of file From 969acc054f1a7c6b3eb4d0e4527467c24676c512 Mon Sep 17 00:00:00 2001 From: ulvii Date: Mon, 29 May 2017 18:38:37 -0700 Subject: [PATCH 12/48] changing to unix line endings --- test/Performance/setup_env_unix.sh | 224 ++++++++++++++--------------- 1 file changed, 112 insertions(+), 112 deletions(-) diff --git a/test/Performance/setup_env_unix.sh b/test/Performance/setup_env_unix.sh index bc439022..ee2d361e 100644 --- a/test/Performance/setup_env_unix.sh +++ b/test/Performance/setup_env_unix.sh @@ -1,113 +1,113 @@ -#!/bin/bash -set -e -if [[ ("$1" = "Ubuntu16" || "$1" = "RedHat7" || "$1" = "Sierra") ]]; then - PLATFORM=$1 -else - echo "First argument must be one of Ubuntu16, RedHat7, Sierra. Exiting..." - exit 1 -fi -if [[ "$2" = "" ]]; then - echo "Second argument must be PHP version in format of 7.x.x.Exiting..." - exit -else - PHP_VERSION=$2 -fi -if [[ ("$3" != "nts" && "$3" != "ts") ]]; then - echo "Thrid argument must be either nts or ts. Exiting..." - exit 1 -else - PHP_THREAD=$3 -fi -if [[ (! -d "$4") || (! -d $4/sqlsrv) || (! -d $4/pdo_sqlsrv) || (! -d $4/shared) ]]; then - echo "Fourth argument must be path to source folder.Path not found.Exiting..." - exit 1 -else - DRIVER_SOURCE_PATH=$4 -fi -rm -rf env_setup.log -touch env_setup.log -if [ $PLATFORM = "Ubuntu16" ]; then - echo "Installing git, libxml, autoconf, openssl..." - yes | sudo apt-get install git autoconf libxml2-dev libssl-dev pkg-config >> env_setup.log 2>&1 - - echo "OK" - echo "Installing MSODBCSQL..." - curl -s https://packages.microsoft.com/keys/microsoft.asc | apt-key add - - curl -s https://packages.microsoft.com/config/ubuntu/16.04/prod.list > /etc/apt/sources.list.d/mssql-release.list - yes | sudo apt-get update >> env_setup.log 2>&1 - yes | sudo ACCEPT_EULA=Y apt-get install msodbcsql >> env_setup.log 2>&1 - yes | sudo apt-get install -qq unixodbc-dev >> env_setup.log 2>&1 -elif [ $PLATFORM = "RedHat7" ]; then - echo "Installing gcc, git, libxml, openssl..." - yes | sudo yum install -y gcc-c++ libxml2-devel git openssl-devel >> env_setup.log 2>&1 - echo "OK" - echo "Installing MSODBCSQL..." - curl -s https://packages.microsoft.com/config/rhel/7/prod.repo > /etc/yum.repos.d/mssql-release.repo - (yes | sudo ACCEPT_EULA=Y yum install -y msodbcsql >> env_setup.log 2>&1) - (yes | sudo yum install -y unixODBC-devel autoconf >> env_setup.log 2>&1) - echo "OK" -elif [ $PLATFORM = "Sierra" ]; then - echo "Installing homebrew..." - yes | /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" >> env_setup.log 2>&1 - echo "OK" - echo "Installing wget..." - #brew install wget >> env_setup.log 2>&1 - echo "OK" - - echo "Installing openssl..." - brew install pkg-config >> env_setup.log 2>&1 - brew install openssl >> env_setup.log 2>&1 - echo "OK" - echo "Installing MSODBCSQL..." - brew tap microsoft/msodbcsql https://github.com/Microsoft/homebrew-msodbcsql >> env_setup.log 2>&1 - brew update >> env_setup.log 2>&1 - yes | ACCEPT_EULA=Y brew install msodbcsql >> env_setup.log 2>&1 - echo "OK" - yes | brew install autoconf >> env_setup.log 2>&1 -fi -echo "Downloading PHP-$PHP_VERSION source tarball..." -wget http://ca1.php.net/get/php-$PHP_VERSION.tar.gz/from/this/mirror -O php-$PHP_VERSION.tar.gz >> env_setup.log 2>&1 -echo "OK" -echo "Extracting PHP source tarball..." -rm -rf php-$PHP_VERSION -tar -xf php-$PHP_VERSION.tar.gz -echo "OK" -cd php-$PHP_VERSION -mkdir ext/sqlsrv ext/pdo_sqlsrv -cp -r $DRIVER_SOURCE_PATH/sqlsrv/* $DRIVER_SOURCE_PATH/shared ext/sqlsrv -cp -r $DRIVER_SOURCE_PATH/pdo_sqlsrv/* $DRIVER_SOURCE_PATH/shared ext/pdo_sqlsrv -./buildconf --force >> ../env_setup.log 2>&1 -CONFIG_OPTIONS="--enable-cli --enable-cgi --enable-pdo --enable-sqlsrv=shared --with-pdo_sqlsrv=shared --with-odbcver=0x0380 --with-zlib --enable-mbstring --prefix=/usr/local" -[ "${PHP_THREAD}" == "ts" ] && CONFIG_OPTIONS=${CONFIG_OPTIONS}" --enable-maintainer-zts" -if [ $PLATFORM = "Sierra" ]; then - CONFIG_OPTIONS=$CONFIG_OPTIONS" --with-openssl=/usr/local/opt/openssl/" -else - CONFIG_OPTIONS=$CONFIG_OPTIONS" --with-openssl" -fi -echo "Configuring PHP..." -(./configure $CONFIG_OPTIONS >> ../env_setup.log 2>&1) -echo "OK" -echo "Compiling PHP and the drivers..." -make >> ../env_setup.log 2>&1 -echo "OK" -sudo make install >> ../env_setup.log 2>&1 -cp php.ini-production php.ini -EXTENSION_DIR=`php-config --extension-dir` -echo "extension=$EXTENSION_DIR/sqlsrv.so" >> php.ini -echo "extension=$EXTENSION_DIR/pdo_sqlsrv.so" >> php.ini -sudo cp php.ini /usr/local/lib -cd .. -php -v -php --ri sqlsrv -php --ri pdo_sqlsrv -echo "Installing Composer..." -wget https://getcomposer.org/installer -O composer-setup.php >> env_setup.log 2>&1 -php composer-setup.php >> env_setup.log 2>&1 -echo "OK" -echo "Installing PHPBench..." -php composer.phar install >> env_setup.log 2>&1 -echo "OK" -echo "Cleaning up..." -rm -rf php-$PHP_VERSION* compser-setup.php -echo "OK" +#!/bin/bash +set -e +if [[ ("$1" = "Ubuntu16" || "$1" = "RedHat7" || "$1" = "Sierra") ]]; then + PLATFORM=$1 +else + echo "First argument must be one of Ubuntu16, RedHat7, Sierra. Exiting..." + exit 1 +fi +if [[ "$2" = "" ]]; then + echo "Second argument must be PHP version in format of 7.x.x.Exiting..." + exit +else + PHP_VERSION=$2 +fi +if [[ ("$3" != "nts" && "$3" != "ts") ]]; then + echo "Thrid argument must be either nts or ts. Exiting..." + exit 1 +else + PHP_THREAD=$3 +fi +if [[ (! -d "$4") || (! -d $4/sqlsrv) || (! -d $4/pdo_sqlsrv) || (! -d $4/shared) ]]; then + echo "Fourth argument must be path to source folder.Path not found.Exiting..." + exit 1 +else + DRIVER_SOURCE_PATH=$4 +fi +rm -rf env_setup.log +touch env_setup.log +if [ $PLATFORM = "Ubuntu16" ]; then + echo "Installing git, libxml, autoconf, openssl..." + yes | sudo apt-get install git autoconf libxml2-dev libssl-dev pkg-config >> env_setup.log 2>&1 + + echo "OK" + echo "Installing MSODBCSQL..." + curl -s https://packages.microsoft.com/keys/microsoft.asc | apt-key add - + curl -s https://packages.microsoft.com/config/ubuntu/16.04/prod.list > /etc/apt/sources.list.d/mssql-release.list + yes | sudo apt-get update >> env_setup.log 2>&1 + yes | sudo ACCEPT_EULA=Y apt-get install msodbcsql >> env_setup.log 2>&1 + yes | sudo apt-get install -qq unixodbc-dev >> env_setup.log 2>&1 +elif [ $PLATFORM = "RedHat7" ]; then + echo "Installing gcc, git, libxml, openssl..." + yes | sudo yum install -y gcc-c++ libxml2-devel git openssl-devel >> env_setup.log 2>&1 + echo "OK" + echo "Installing MSODBCSQL..." + curl -s https://packages.microsoft.com/config/rhel/7/prod.repo > /etc/yum.repos.d/mssql-release.repo + (yes | sudo ACCEPT_EULA=Y yum install -y msodbcsql >> env_setup.log 2>&1) + (yes | sudo yum install -y unixODBC-devel autoconf >> env_setup.log 2>&1) + echo "OK" +elif [ $PLATFORM = "Sierra" ]; then + echo "Installing homebrew..." + yes | /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" >> env_setup.log 2>&1 + echo "OK" + echo "Installing wget..." + #brew install wget >> env_setup.log 2>&1 + echo "OK" + + echo "Installing openssl..." + brew install pkg-config >> env_setup.log 2>&1 + brew install openssl >> env_setup.log 2>&1 + echo "OK" + echo "Installing MSODBCSQL..." + brew tap microsoft/msodbcsql https://github.com/Microsoft/homebrew-msodbcsql >> env_setup.log 2>&1 + brew update >> env_setup.log 2>&1 + yes | ACCEPT_EULA=Y brew install msodbcsql >> env_setup.log 2>&1 + echo "OK" + yes | brew install autoconf >> env_setup.log 2>&1 +fi +echo "Downloading PHP-$PHP_VERSION source tarball..." +wget http://ca1.php.net/get/php-$PHP_VERSION.tar.gz/from/this/mirror -O php-$PHP_VERSION.tar.gz >> env_setup.log 2>&1 +echo "OK" +echo "Extracting PHP source tarball..." +rm -rf php-$PHP_VERSION +tar -xf php-$PHP_VERSION.tar.gz +echo "OK" +cd php-$PHP_VERSION +mkdir ext/sqlsrv ext/pdo_sqlsrv +cp -r $DRIVER_SOURCE_PATH/sqlsrv/* $DRIVER_SOURCE_PATH/shared ext/sqlsrv +cp -r $DRIVER_SOURCE_PATH/pdo_sqlsrv/* $DRIVER_SOURCE_PATH/shared ext/pdo_sqlsrv +./buildconf --force >> ../env_setup.log 2>&1 +CONFIG_OPTIONS="--enable-cli --enable-cgi --enable-pdo --enable-sqlsrv=shared --with-pdo_sqlsrv=shared --with-odbcver=0x0380 --with-zlib --enable-mbstring --prefix=/usr/local" +[ "${PHP_THREAD}" == "ts" ] && CONFIG_OPTIONS=${CONFIG_OPTIONS}" --enable-maintainer-zts" +if [ $PLATFORM = "Sierra" ]; then + CONFIG_OPTIONS=$CONFIG_OPTIONS" --with-openssl=/usr/local/opt/openssl/" +else + CONFIG_OPTIONS=$CONFIG_OPTIONS" --with-openssl" +fi +echo "Configuring PHP..." +(./configure $CONFIG_OPTIONS >> ../env_setup.log 2>&1) +echo "OK" +echo "Compiling PHP and the drivers..." +make >> ../env_setup.log 2>&1 +echo "OK" +sudo make install >> ../env_setup.log 2>&1 +cp php.ini-production php.ini +EXTENSION_DIR=`php-config --extension-dir` +echo "extension=$EXTENSION_DIR/sqlsrv.so" >> php.ini +echo "extension=$EXTENSION_DIR/pdo_sqlsrv.so" >> php.ini +sudo cp php.ini /usr/local/lib +cd .. +php -v +php --ri sqlsrv +php --ri pdo_sqlsrv +echo "Installing Composer..." +wget https://getcomposer.org/installer -O composer-setup.php >> env_setup.log 2>&1 +php composer-setup.php >> env_setup.log 2>&1 +echo "OK" +echo "Installing PHPBench..." +php composer.phar install >> env_setup.log 2>&1 +echo "OK" +echo "Cleaning up..." +rm -rf php-$PHP_VERSION* compser-setup.php +echo "OK" echo "Setup completed!" \ No newline at end of file From d84f8412bf31145c04b1ef7cd9c8f516a0985925 Mon Sep 17 00:00:00 2001 From: ulvii Date: Tue, 30 May 2017 10:13:43 -0700 Subject: [PATCH 13/48] Update setup_env_unix.sh --- test/Performance/setup_env_unix.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Performance/setup_env_unix.sh b/test/Performance/setup_env_unix.sh index ee2d361e..08587e11 100644 --- a/test/Performance/setup_env_unix.sh +++ b/test/Performance/setup_env_unix.sh @@ -51,7 +51,7 @@ elif [ $PLATFORM = "Sierra" ]; then yes | /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" >> env_setup.log 2>&1 echo "OK" echo "Installing wget..." - #brew install wget >> env_setup.log 2>&1 + brew install wget >> env_setup.log 2>&1 echo "OK" echo "Installing openssl..." From b6736092397cfae4e5def2f8c6075253a3ec0f7e Mon Sep 17 00:00:00 2001 From: ulvii Date: Tue, 30 May 2017 11:49:09 -0700 Subject: [PATCH 14/48] Adding a workaround by installing svn, because the default svn on Mac is broken --- test/Performance/setup_env_unix.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/Performance/setup_env_unix.sh b/test/Performance/setup_env_unix.sh index 08587e11..d9a75a84 100644 --- a/test/Performance/setup_env_unix.sh +++ b/test/Performance/setup_env_unix.sh @@ -53,7 +53,9 @@ elif [ $PLATFORM = "Sierra" ]; then echo "Installing wget..." brew install wget >> env_setup.log 2>&1 echo "OK" - + echo "Installing svn..." + brew install svn >> env_setup.log 2>&1 + echo "OK" echo "Installing openssl..." brew install pkg-config >> env_setup.log 2>&1 brew install openssl >> env_setup.log 2>&1 From 8eae559fb8adb21f4776f6a08cfa04ff8c7dee27 Mon Sep 17 00:00:00 2001 From: ulvii Date: Wed, 31 May 2017 18:11:10 -0700 Subject: [PATCH 15/48] Initial commit for windows env setup script --- test/Performance/setup_env_windows.ps1 | 62 ++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 test/Performance/setup_env_windows.ps1 diff --git a/test/Performance/setup_env_windows.ps1 b/test/Performance/setup_env_windows.ps1 new file mode 100644 index 00000000..184ac08d --- /dev/null +++ b/test/Performance/setup_env_windows.ps1 @@ -0,0 +1,62 @@ +Param( + [Parameter(Mandatory=$True,Position=1)] + [string]$PHP_VERSION, + [Parameter(Mandatory=$True,Position=2)] + [string]$PHP_THREAD, + [Parameter(Mandatory=$True,Position=3)] + [string]$DRIVER_SOURCE_PATH, +[Parameter(Mandatory=$True,Position=4)] + [string]$ARCH + ) + +$PHP_VERSION_MINOR=$PHP_VERSION.split(".")[1] +$startingDir=$pwd.Path +$tempFolder=Join-Path $startingDir "temp" +echo $tempFolder + +Remove-Item temp -Recurse -Force -ErrorAction Ignore +New-Item -ItemType directory -Path temp + +Write-Host "Downloading Git..." +(New-Object System.Net.WebClient).DownloadFile('https://github.com/git-for-windows/git/releases/download/v2.13.0.windows.1/Git-2.13.0-64-bit.exe', "$tempFolder\git.exe") +Write-Host "Installing Git..." +.\temp\git.exe /SILENT | Out-Null +Write-Host "Downloading MSODBCSQL..." +(New-object System.Net.WebClient).DownloadFile('https://download.microsoft.com/download/D/5/E/D5EEF288-A277-45C8-855B-8E2CB7E25B96/x64/msodbcsql.msi', "$tempFolder\msodbcsql.msi") +Write-Host "Installing MSODBCSQL..." +msiexec /quiet /passive /qn /i $tempFolder\msodbcsql.msi IACCEPTMSODBCSQLLICENSETERMS=YES | Out-Null +Write-Host "Downloading 7-Zip..." +(New-object System.Net.WebClient).DownloadFile("http://www.7-zip.org/a/7z1604-x64.exe", "$tempFolder\7z1604-x64.exe") +Write-Host "Installing 7-Zip..." +.\temp\7z1604-x64.exe /S | Out-Null +set-alias sz "$env:ProgramFiles\7-Zip\7z.exe" +Write-Host "Downloading PHP-SDK..." +(New-Object System.Net.WebClient).DownloadFile('http://windows.php.net/downloads/php-sdk/php-sdk-binary-tools-20110915.zip', "$tempFolder\binary_tools.zip") +Write-Host "Downloading PHP-$PHP_VERSION source..." +(New-Object System.Net.WebClient).DownloadFile("http://windows.php.net/downloads/releases/php-$PHP_VERSION-src.zip", "$tempFolder\php-$PHP_VERSION-src.zip") +Write-Host "Downloading Dependencies..." +(New-Object System.Net.WebClient).DownloadFile("http://windows.php.net/downloads/php-sdk/deps-7.$PHP_VERSION_MINOR-vc14-$ARCH.7z", "$tempFolder\deps-7.$PHP_VERSION_MINOR-vc14-$ARCH.7z") + +Add-Type -AssemblyName System.IO.Compression.FileSystem +Remove-Item C:\php-sdk -Recurse -Force -ErrorAction Ignore +New-Item -ItemType directory -Path C:\php-sdk +[System.IO.Compression.ZipFile]::ExtractToDirectory("$tempFolder\binary_tools.zip", "C:\php-sdk") +cd C:\php-sdk\ +bin\phpsdk_buildtree.bat phpdev +New-Item -ItemType directory -Path .\phpdev\vc14 +Copy-Item .\phpdev\vc9\* phpdev\vc14\ -recurse +[System.IO.Compression.ZipFile]::ExtractToDirectory("$tempFolder\php-$PHP_VERSION-src.zip", "C:\php-sdk\phpdev\vc14\$ARCH\") +set-alias sz "$env:ProgramFiles\7-Zip\7z.exe" +sz x $tempFolder\deps-7.$PHP_VERSION_MINOR-vc14-$ARCH.7z -oC:\php-sdk\phpdev\vc14\$ARCH\ + +bin\phpsdk_setvars.bat +cd C:\php-sdk\phpdev\vc14\$ARCH\php-$PHP_VERSION-src +.\buildconf --force +$CONFIG_OPTIONS="--enable-cli --enable-cgi --enable-pdo --enable-sqlsrv=shared --with-pdo_sqlsrv=shared --with-odbcver=0x0380 --with-zlib --enable-mbstring" +if ($PHP_THREAD -ceq "nts") { + $CONFIG_OPTIONS=$CONFIG_OPTIONS + "--disable-zts" +} +.\configure $CONFIG_OPTIONS +nmake + + From 6898826636224d36c4797844a2d0911d28c4288f Mon Sep 17 00:00:00 2001 From: ulvii Date: Thu, 1 Jun 2017 17:35:44 -0700 Subject: [PATCH 16/48] Windows setup working script --- test/Performance/compile_php.bat | 3 +++ test/Performance/setup_env_windows.ps1 | 35 ++++++++++++++++++++------ 2 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 test/Performance/compile_php.bat diff --git a/test/Performance/compile_php.bat b/test/Performance/compile_php.bat new file mode 100644 index 00000000..e08b0f3a --- /dev/null +++ b/test/Performance/compile_php.bat @@ -0,0 +1,3 @@ +set options=%2 +set options=%options:"=% +C:\php-sdk\bin\phpsdk_setvars.bat && "c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %1 && .\buildconf --force && .\configure %options% && nmake && nmake install \ No newline at end of file diff --git a/test/Performance/setup_env_windows.ps1 b/test/Performance/setup_env_windows.ps1 index 184ac08d..3fa72aa1 100644 --- a/test/Performance/setup_env_windows.ps1 +++ b/test/Performance/setup_env_windows.ps1 @@ -12,13 +12,13 @@ Param( $PHP_VERSION_MINOR=$PHP_VERSION.split(".")[1] $startingDir=$pwd.Path $tempFolder=Join-Path $startingDir "temp" -echo $tempFolder + Remove-Item temp -Recurse -Force -ErrorAction Ignore New-Item -ItemType directory -Path temp Write-Host "Downloading Git..." -(New-Object System.Net.WebClient).DownloadFile('https://github.com/git-for-windows/git/releases/download/v2.13.0.windows.1/Git-2.13.0-64-bit.exe', "$tempFolder\git.exe") +(New-Object System.Net.WebClient).DownloadFile('https://github.com/git-for-windows/git/releases/download/v2.13.0.windows.1/Git-2.13.0-64-bit.exe', "$tempFolder\git.exe") Write-Host "Installing Git..." .\temp\git.exe /SILENT | Out-Null Write-Host "Downloading MSODBCSQL..." @@ -50,13 +50,34 @@ set-alias sz "$env:ProgramFiles\7-Zip\7z.exe" sz x $tempFolder\deps-7.$PHP_VERSION_MINOR-vc14-$ARCH.7z -oC:\php-sdk\phpdev\vc14\$ARCH\ bin\phpsdk_setvars.bat + cd C:\php-sdk\phpdev\vc14\$ARCH\php-$PHP_VERSION-src -.\buildconf --force -$CONFIG_OPTIONS="--enable-cli --enable-cgi --enable-pdo --enable-sqlsrv=shared --with-pdo_sqlsrv=shared --with-odbcver=0x0380 --with-zlib --enable-mbstring" + +New-Item -ItemType directory -Path .\ext\sqlsrv +New-Item -ItemType directory -Path .\ext\pdo_sqlsrv +Copy-Item $DRIVER_SOURCE_PATH\sqlsrv\* .\ext\sqlsrv\ -recurse +Copy-Item $DRIVER_SOURCE_PATH\shared\ .\ext\sqlsrv\ -recurse +Copy-Item $DRIVER_SOURCE_PATH\pdo_sqlsrv\* .\ext\pdo_sqlsrv\ -recurse +Copy-Item $DRIVER_SOURCE_PATH\shared\ .\ext\pdo_sqlsrv\ -recurse + + +$CONFIG_OPTIONS="--enable-cli --enable-cgi --enable-sqlsrv=shared --enable-pdo=shared --with-pdo-sqlsrv=shared --with-odbcver=0x0380 --enable-mbstring --with-openssl" if ($PHP_THREAD -ceq "nts") { - $CONFIG_OPTIONS=$CONFIG_OPTIONS + "--disable-zts" + $CONFIG_OPTIONS=$CONFIG_OPTIONS + " --disable-zts" } -.\configure $CONFIG_OPTIONS -nmake +& $startingDir\compile_php.bat $ARCH $CONFIG_OPTIONS +Copy-Item php.ini-production php.ini +Add-Content php.ini "extension=C:\php\ext\php_sqlsrv.dll" +Add-Content php.ini "extension=C:\php\ext\php_pdo_sqlsrv.dll" +Add-Content php.ini "extension=C:\php\ext\php_openssl.dll" +Move-Item php.ini C:\Windows -force +Copy-Item C:\php-sdk\phpdev\vc14\$ARCH\deps\bin\ssleay32.dll C:\Windows -force +Copy-Item C:\php-sdk\phpdev\vc14\$ARCH\deps\bin\libeay32.dll C:\Windows -force + +cd $startingDir +set-alias php "C:\php\php.exe" +wget https://getcomposer.org/installer -O composer-setup.php +php composer-setup.php +php composer.phar install \ No newline at end of file From 44671291e6bb5bdffaf476c4c7432136d0adfe73 Mon Sep 17 00:00:00 2001 From: ulvii Date: Fri, 2 Jun 2017 15:53:22 -0700 Subject: [PATCH 17/48] Update README.md --- test/Performance/README.md | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/test/Performance/README.md b/test/Performance/README.md index 8b11445d..ddac6707 100644 --- a/test/Performance/README.md +++ b/test/Performance/README.md @@ -1,21 +1,20 @@ -## 1. Install Composer - Dependency Manager for PHP -https://getcomposer.org/ +## 1. Setup Environment on a clean machine - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" - php -r "if (hash_file('SHA384', 'composer-setup.php') === '669656bab3166a7aff8a7506b8cb2d1c292f042046c5a994c43155c0be6190fa0355160742ab2e1c88d40d5be660b410') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" - php composer-setup.php - php -r "unlink('composer-setup.php');" - -## 2. Install PHPBench - A Benchmark Runner for PHP -http://phpbench.readthedocs.io/en/latest/ +### Windows +Install Visual Studio 2015 before running the following commands. Make sure C++ tools are enabled. +Run `cmd` as administrator. -Make sure git is installed and in your PATH env. Navigate into Performance folder and run: + powershell + .\setup_env_windows.ps1 +### Ubuntu 16 + sudo env “PATH=$PATH” bash setup_env_unix.sh Ubuntu16 +### RedHat 7 + sudo env “PATH=$PATH” bash setup_env_unix.sh RedHat7 +### Sierra +`brew` cannot be run with `sudo` on Sierra. Either enable passwordless `sudo` on the machine or enter the password when prompted. - composer install - -## 3. Run benchmarks - -PHPBench will use the default PHP in PATH env. To specify a different PHP binary, use `--php-binary path_to_php`. Make sure `sqlsrv` and `pdo_sqlsrv` are loaded. Edit `lib/connect.php` with connection credentials. Run benchmarks. + bash setup_env_unix.sh Sierra +## 3. Run benchmarks - Subject to change once the process is automated Run sqlsrv benchmarks: From b151f20e256675c1157cd7425ae077bebb1d658c Mon Sep 17 00:00:00 2001 From: ulvii Date: Fri, 2 Jun 2017 16:02:34 -0700 Subject: [PATCH 18/48] Update README.md --- test/Performance/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Performance/README.md b/test/Performance/README.md index ddac6707..8faf63a8 100644 --- a/test/Performance/README.md +++ b/test/Performance/README.md @@ -1,4 +1,4 @@ -## 1. Setup Environment on a clean machine +## Setup Environment on a clean machine ### Windows Install Visual Studio 2015 before running the following commands. Make sure C++ tools are enabled. @@ -14,7 +14,7 @@ Run `cmd` as administrator. `brew` cannot be run with `sudo` on Sierra. Either enable passwordless `sudo` on the machine or enter the password when prompted. bash setup_env_unix.sh Sierra -## 3. Run benchmarks - Subject to change once the process is automated +## Run benchmarks - Subject to change once the process is automated Run sqlsrv benchmarks: From 188fba08598543644f5df1fa1224064d39a4db6f Mon Sep 17 00:00:00 2001 From: ulvii Date: Fri, 2 Jun 2017 16:46:03 -0700 Subject: [PATCH 19/48] Update SqlsrvInsertBench.php --- test/Performance/benchmark/sqlsrv/regular/SqlsrvInsertBench.php | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Performance/benchmark/sqlsrv/regular/SqlsrvInsertBench.php b/test/Performance/benchmark/sqlsrv/regular/SqlsrvInsertBench.php index b5959cdd..43a451fd 100644 --- a/test/Performance/benchmark/sqlsrv/regular/SqlsrvInsertBench.php +++ b/test/Performance/benchmark/sqlsrv/regular/SqlsrvInsertBench.php @@ -14,6 +14,7 @@ class SqlsrvInsertBench{ public function setTableName(){ $this->tableName = "datatypes_".rand(); } + public function connect(){ $this->conn = SqlsrvUtil::connect(); } From 6b2ead8a4c35df9c8ad960d32857a7957f029ea3 Mon Sep 17 00:00:00 2001 From: ulvii Date: Mon, 5 Jun 2017 17:04:57 -0700 Subject: [PATCH 20/48] 1. Modifying Sqlsrv benchmarks to use sqlsrv_fetch_array to make the fetch consistent with PDO_SQLSRV. 2. Modifying PDO_SQLSRV benchmarks to use exec() instead of query() --- test/Performance/lib/PDOSqlsrvUtil.php | 16 ++++++++-------- test/Performance/lib/SqlsrvUtil.php | 17 ++++++++++------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/test/Performance/lib/PDOSqlsrvUtil.php b/test/Performance/lib/PDOSqlsrvUtil.php index bba6d845..2e82a476 100644 --- a/test/Performance/lib/PDOSqlsrvUtil.php +++ b/test/Performance/lib/PDOSqlsrvUtil.php @@ -99,7 +99,7 @@ class PDOSqlsrvUtil{ $sql = "SELECT * FROM $tableName"; $stmt = self::prepare( $conn, $sql ); self::execute( $stmt ); - while ( $row = self::fetch( $stmt )){} + while ( $row = self::fetch( $stmt )){} } public static function deleteWithPrepare( $conn, $tableName ){ @@ -151,37 +151,37 @@ class PDOSqlsrvUtil{ private function createDatabase( $conn, $dbName ){ $sql = "CREATE DATABASE $dbName"; - self::query( $conn, $sql ); + $conn->exec( $sql ); } public static function dropDatabase( $conn, $dbName ){ $sql = "USE MASTER;DROP DATABASE $dbName"; - self::query( $conn, $sql ); + $conn->exec( $sql ); } public static function createTable( $conn, $tableName, $params ){ $sql = "CREATE TABLE $tableName ($params)"; - self::query( $conn, $sql ); + $conn->exec( $sql ); } public static function dropTable( $conn, $tableName ){ $sql = "DROP TABLE $tableName"; - self::query( $conn, $sql ); + $conn->exec( $sql ); } private function useDatabase( $conn, $dbName ){ $sql = "USE $dbName"; - self::query( $conn, $sql ); + $conn->exec( $sql ); } private function createStoredProc( $conn, $procName, $params, $text ){ $sql = "CREATE PROCEDURE $procName $params AS $text"; - self::query( $conn, $sql ); + $conn->exec( $sql ); } private function dropStoredProc( $conn, $procName ){ $sql = "DROP PROCEDURE $procName"; - self::query( $conn, $sql ); + $conn->exec( $sql ); } private function query( $conn, $sql ){ diff --git a/test/Performance/lib/SqlsrvUtil.php b/test/Performance/lib/SqlsrvUtil.php index e80fe8ca..fc66726a 100644 --- a/test/Performance/lib/SqlsrvUtil.php +++ b/test/Performance/lib/SqlsrvUtil.php @@ -24,8 +24,7 @@ class SqlsrvUtil{ public static function selectVersion( $conn ){ $sql = "SELECT @@Version"; $stmt = self::query( $conn, $sql ); - self::fetch( $stmt ); - return self::getField( $stmt, 0 ); + return self::fetchArray( $stmt ); } public static function createDbTableProc( $conn, $databaseName, $tableName, $procName ){ @@ -105,11 +104,7 @@ class SqlsrvUtil{ $sql = "SELECT * FROM $tableName"; $stmt = self::prepare( $conn, $sql, array()); self::execute( $stmt ); - while ( self::fetch( $stmt )){ - for ( $i=0; $i<10; $i++ ){ - self::getField( $stmt, $i ); - } - } + while( $row = self::fetchArray( $stmt ) ) {} } public static function createCRUDTable( $conn, $tableName ){ @@ -148,6 +143,14 @@ class SqlsrvUtil{ return $ret; } + public static function fetchArray( $stmt ){ + $row = sqlsrv_fetch_array( $stmt ); + if ( $row === false ){ + die( print_r( sqlsrv_errors(), true)); + } + return $row; + } + public static function getField( $stmt, $index ){ return sqlsrv_get_field( $stmt, $index ); } From c655d04226e8ce4d94cca2a7532946189ff3fdd0 Mon Sep 17 00:00:00 2001 From: ulvii Date: Fri, 16 Jun 2017 18:30:16 -0700 Subject: [PATCH 21/48] Initial commit for run-tests script --- test/Performance/run-perf_tests.py | 376 +++++++++++++++++++++++++++-- 1 file changed, 356 insertions(+), 20 deletions(-) diff --git a/test/Performance/run-perf_tests.py b/test/Performance/run-perf_tests.py index b6776f24..37a41091 100644 --- a/test/Performance/run-perf_tests.py +++ b/test/Performance/run-perf_tests.py @@ -1,32 +1,368 @@ import shutil +from shutil import copyfile import os import sys +import argparse +import subprocess +import fileinput +import subprocess +from subprocess import call +import xml.etree.ElementTree as ET +import pyodbc +import platform +import re +import datetime +from time import strftime + +sqlsrv_regular_path = "benchmark"+ os.sep + "sqlsrv" + os.sep + "regular" +sqlsrv_large_path = "benchmark"+ os.sep + "sqlsrv" + os.sep + "large" +pdo_regular_path = "benchmark"+ os.sep + "pdo_sqlsrv" + os.sep + "regular" +pdo_large_path = "benchmark"+ os.sep + "pdo_sqlsrv" + os.sep + "large" +connect_file = "lib" + os.sep + "connect.php" +connect_file_bak = connect_file + ".bak" -def check_exe(name): - path_to_exe = shutil.which(name) - if path_to_exe is not None: - print(name + " found: " + path_to_exe) +def validate_platform( platform_name ): + platforms = [ + "Windows10" + , "WidnowsServer2016" + , "WindowsServer2012" + , "Ubuntu16" + , "RedHat7" + , "Sierra"] + if platform_name not in platforms: + print ( "Platform must be one of the following:" ) + print( platforms ) + exit( 1 ) + +class DB( object ): + def __init__ ( self + , server_name = None + , database_name = None + , username = None + , password = None): + self.server_name = server_name + self.database_name = database_name + self.username = username + self.password = password + +class XMLResult( object ): + def __init__ ( self + , benchmark_name = None + , success = None + , duration = None + , memory = None + , error_message = None ): + self.benchmark_name = benchmark_name + self.success = success + self.duration = duration + self.memory = memory + self.error_message = error_message + +def get_test_name( name ): + test_name_dict = { + 'SqlsrvConnectionBench': 'connection' + , 'SqlsrvCreateDbTableProcBench': 'create' + , 'SqlsrvInsertBench': 'crud-create' + , 'SqlsrvFetchBench': 'crud-retrieve' + , 'SqlsrvUpdateBench': 'crud-update' + , 'SqlsrvDeleteBench': 'crud-delete' + , 'SqlsrvFetchLargeBench': 'large' + , 'SqlsrvSelectVersionBench': 'version' + , 'PDOConnectionBench': 'connection' + , 'PDOCreateDbTableProcBench': 'create' + , 'PDOInsertBench': 'crud-create' + , 'PDOFetchBench': 'crud-retrieve' + , 'PDOUpdateBench': 'crud-update' + , 'PDODeleteBench': 'crud-delete' + , 'PDOFetchLargeBench': 'large' + , 'PDOSelectVersionBench': 'version' + } + return test_name_dict[ name ] + +def get_run_command( path_to_tests, iterations, dump_file ): + command = "vendor/bin/phpbench run {0} --iterations {1} --dump-file={2}" + return command.format( path_to_tests, iterations, dump_file ) + +def get_id( conn, id_field, table, name_field, name): + query = "SELECT {0} FROM {1} WHERE {2}='{3}'" + cursor = conn.cursor() + cursor.execute( query.format( id_field, table, name_field, name )) + id = cursor.fetchone() + cursor.close() + if id is not None: + return id[0] + return id + +def get_test_database(): + test_db = DB() + for line in open( connect_file ): + if "server" in line: + test_db.server_name = line.split("=")[1].strip()[1:-2] + elif "database" in line: + test_db.database_name = line.split("=")[1].strip()[1:-2] + elif "uid" in line: + test_db.username = line.split("=")[1].strip()[1:-2] + elif "pwd" in line: + test_db.password = line.split("=")[1].strip()[1:-2] + return test_db + +def connect( db ): + return pyodbc.connect( + driver="{ODBC Driver 13 for SQL Server}" + , host=db.server_name + , database=db.database_name + , user=db.username + , password=db.password + , autocommit = True) + +def get_server_version( server): + conn = connect( server ) + cursor = conn.cursor() + cursor.execute( "SELECT @@VERSION") + version = cursor.fetchone()[0] + cursor.close() + return version + +def insert_server_entry( conn, server_name, server_version ): + query = "INSERT INTO Servers ( HostName, Version ) VALUES ( '{0}', '{1}' )" + cursor = conn.cursor() + cursor.execute( query.format( server_name, server_version )) + cursor.close() + +def insert_client_entry ( conn, name ): + query = "INSERT INTO Clients ( HostName ) VALUES( '{0}' )" + cursor = conn.cursor() + cursor.execute( query.format( name )) + cursor.close() + +def insert_team_entry ( conn, name ): + query = "INSERT INTO Teams ( TeamName ) VALUES( '{0}' )" + cursor = conn.cursor() + cursor.execute( query.format( name )) + cursor.close() + +def insert_test_entry( conn, name ): + #TO-DO Remove unnecessary columns from the table and fix the query string. Amd64 and 0 are used to bypass not null + query = "INSERT INTO PerformanceTests ( TestName, Arch, HashVer ) VALUES( '{0}', 'Amd64', 0 )" + cursor = conn.cursor() + cursor.execute( query.format( name )) + cursor.close() + +def get_server_id( conn, test_db ): + server_id = get_id( conn, "ServerId", "Servers", "HostName", test_db.server_name ) + if server_id is None: + insert_server_entry( conn, test_db.server_name, get_server_version( test_db )) + server_id = get_id( conn, "ServerId", "Servers", "HostName", test_db.server_name ) + return server_id + +def get_client_id( conn ): + client_name = platform.node() + client_id = get_id( conn, "ClientId", "Clients", "HostName", client_name ) + if client_id is None: + insert_client_entry( conn, client_name ) + client_id = get_id( conn, "ClientId", "Clients", "HostName", client_name ) + return client_id + +def get_team_id( conn ): + team_name = "PHP" + team_id = get_id( conn, "TeamId", "Teams", "TeamName", team_name) + if team_id is None: + insert_team_entry( conn, team_name ) + team_id = get_id( conn, "TeamId", "Teams", "TeamName", team_name) + return team_id + +def get_test_id( conn, test_name ): + test_id = get_id( conn, "TestId", "PerformanceTests", "TestName", test_name ) + if test_id is None: + insert_test_entry( conn, test_name ) + test_id = get_id( conn, "TestId", "PerformanceTests", "TestName", test_name ) + return test_id + +def insert_result_entry_and_get_id( conn, test_id, client_id, driver_id, server_id, team_id, success ): + query = "INSERT INTO PerformanceResults( TestId, ClientId, DriverId, ServerId, TeamId, Success ) OUTPUT INSERTED.ResultId VALUES( {0}, {1}, {2}, {3}, {4}, {5} )" + cursor = conn.cursor() + cursor.execute( query.format( test_id, client_id, driver_id, server_id, team_id, success )) + result_id = cursor.fetchone() + cursor.close() + if result_id is not None: + return result_id[0] + return id + +def insert_key_value( conn, table_name, result_id, key, value ): + query = "INSERT INTO {0} ( ResultId, name, value ) VALUES( ?, ?, ? )" + cursor = conn.cursor() + cursor.execute( query.format( table_name ), ( result_id, key, value ) ) + cursor.close() + +def get_php_arch(): + p = subprocess.Popen( "php -r 'echo PHP_INT_SIZE;'", stdout=subprocess.PIPE, shell = True ) + out, err = p.communicate() + if out.decode('ascii') == "8": + return "x64" + elif out.decode('ascii') == "4": + return "x86" + +def get_php_thread(): + if os.name == 'nt': + command = "php -i | findstr 'Thread'" else: - sys.exit(name + " not found. Exiting...") + command = "php -i | grep 'Thread'" + p = subprocess.Popen( command, stdout=subprocess.PIPE, shell = True ) + out, err = p.communicate() + if out.decode('ascii').split()[3].strip() == 'disabled': + return "nts" + else: + return "ts" +def enable_mars(): + print( "Enabling MARS...") + with fileinput.FileInput( connect_file, inplace=True, backup='.bak') as file: + for line in file: + print( line.replace( "$mars=false;", "$mars=true;" ), end='') -print("Checking requirements...\n") +def disable_mars(): + print( "Disabling MARS...") + os.remove( connect_file ) + copyfile( connect_file_bak, connect_file ) -check_exe("php") +def enable_pooling(): + print( "Enabling Pooling...") + if os.name == 'nt': + with fileinput.FileInput( connect_file, inplace=True, backup='.bak') as file: + for line in file: + print( line.replace( "$pooling=false;", "$pooling=true;" ), end='') + else: + # Get the location of odbcinst.ini + odbcinst = os.popen( "odbcinst -j" ).read().splitlines()[1].split()[1] + odbcinst_bak = odbcinst + ".bak" + + # Create a copy of odbcinst.ini + copyfile( odbcinst, odbcinst_bak ) + + # Lines to enable Connection pooling + lines_to_append="CPTimeout=5\n[ODBC]\nPooling=Yes\n" + + with open( odbcinst, "a" ) as f: + f.write( lines_to_append ) -print("\nPHP INFO:\n") -os.system("php -v") +def disable_pooling(): + print("Disabling Pooling...") + if os.name == 'nt': + os.remove( connect_file ) + copyfile( connect_file_bak, connect_file ) + else: + # Get the location of odbcinst.ini + odbcinst = os.popen( "odbcinst -j" ).read().splitlines()[1].split()[1] + odbcinst_bak = odbcinst + ".bak" + os.remove( odbcinst ) + copyfile( odbcinst_bak, odbcinst ) + os.remove( odbcinst_bak ) -print("\nChecking if sqlsrv and pdo_sqslrv are loaded...\n") -if os.system("php --ri sqlsrv") != 0: - sys.exit("Exiting...") -if os.system("php --ri pdo_sqlsrv") != 0: - sys.exit("Exiting...") +def run_tests( iterations, iterations_large ): + print("Running the tests...") + call( get_run_command( sqlsrv_regular_path, iterations, "sqlsrv-regular.xml" ), shell=True, stdout=open( os.devnull, 'wb' )) + call( get_run_command( sqlsrv_large_path, iterations_large, "sqlsrv-large.xml" ), shell=True, stdout=open( os.devnull, 'wb' )) + + call( get_run_command( pdo_regular_path, iterations, "pdo_sqlsrv-regular.xml" ), shell=True, stdout=open( os.devnull, 'wb' )) + call( get_run_command( pdo_large_path, iterations_large, "pdo_sqlsrv-large.xml" ), shell=True, stdout=open( os.devnull, 'wb' )) -print("Installing Composer...") -os.system("php download_composer_setup.php") -os.system("php composer-setup.php") -os.system("php unlink_composer_setup.php") +def parse_results( dump_file ): + xml_results = [] + tree = ET.parse( dump_file ) + root = tree.getroot() + for benchmark in root[0].findall( 'benchmark' ): + xml_result = XMLResult() + xml_result.benchmark_name = benchmark.get( 'class' )[1:] + errors = benchmark[0][0].find( 'errors' ) + if( errors is not None ): + xml_result.success = 0 + xml_result.error_message = errors[0].text + else: + xml_result.success = 1 + xml_result.duration = benchmark[0][0].find( 'stats' ).get( 'sum' ) + memory_peak = 0 + for iteration in benchmark[0][0].findall( 'iteration' ): + iter_memory_peak = int( iteration.get( 'mem-peak' )) + if iter_memory_peak > memory_peak: + memory_peak = iter_memory_peak + xml_result.memory = memory_peak + xml_results.append( xml_result ) + return xml_results -print("Installing PHPBench...") -os.system("php composer.phar install") \ No newline at end of file +def parse_and_store_results( dump_file, test_db, result_db, platform, driver, start_time, mars, pooling ): + conn = connect( result_db ) + + server_id = get_server_id( conn, test_db ) + client_id = get_client_id( conn ) + team_id = get_team_id( conn ) + # TO - DO Add a function to insert a driver entry + driver_id=1 + + arch = get_php_arch() + thread = get_php_thread() + cursor = conn.cursor() + results = parse_results( dump_file ) + + for result in results: + test_name = get_test_name( result.benchmark_name ) + test_id = get_test_id( conn, test_name ) + result_id = insert_result_entry_and_get_id( conn, test_id, client_id, driver_id, server_id, team_id, result.success ) + + if result.success: + insert_key_value( conn, "KeyValueTableBigInt", result_id, "duration", result.duration ) + insert_key_value( conn, "KeyValueTableBigInt", result_id, "memory", result.memory ) + else: + insert_key_value( conn, "KeyValueTableString", result_id, "error", result.error_message ) + + insert_key_value( conn, "KeyValueTableDate" , result_id, "startTime", start_time ) + insert_key_value( conn, "KeyValueTableBigInt", result_id, "mars" , mars ) + insert_key_value( conn, "KeyValueTableBigInt", result_id, "pooling" , pooling ) + insert_key_value( conn, "KeyValueTableString", result_id, "driver" , driver ) + insert_key_value( conn, "KeyValueTableString", result_id, "arch" , arch ) + insert_key_value( conn, "KeyValueTableString", result_id, "os" , platform ) + insert_key_value( conn, "KeyValueTableString", result_id, "thread" , thread ) + +def parse_and_store_results_all( test_db, result_db, platform, start_time, mars, pooling ): + print("Parsing and storing the results...") + parse_and_store_results( "sqlsrv-regular.xml", test_db, result_db, platform, "sqlsrv", start_time, mars, pooling ) + parse_and_store_results( "sqlsrv-large.xml", test_db, result_db, platform, "sqlsrv", start_time, mars, pooling ) + parse_and_store_results( "pdo_sqlsrv-regular.xml", test_db, result_db, platform, "pdo_sqlsrv", start_time, mars, pooling ) + parse_and_store_results( "pdo_sqlsrv-large.xml", test_db, result_db, platform, "pdo_sqlsrv", start_time, mars, pooling ) + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( '-platform', '--PLATFORM', required=True ) + parser.add_argument( '-iterations', '--ITERATIONS', type=int , required=True ) + parser.add_argument( '-iterations-large', '--ITERATIONS_LARGE',type=int , required=True ) + parser.add_argument( '-result-server', '--RESULT_SERVER', required=True ) + parser.add_argument( '-result-db', '--RESULT_DB', required=True ) + parser.add_argument( '-result-uid', '--RESULT_UID', required=True ) + parser.add_argument( '-result-pwd', '--RESULT_PWD', required=True ) + args = parser.parse_args() + + validate_platform( args.PLATFORM ) + result_db = DB( args.RESULT_SERVER, args.RESULT_DB, args.RESULT_UID, args.RESULT_PWD ) + test_db = get_test_database() + fmt = "%Y-%m-%d %H:%M:%S.0000000" + + print("Running the tests with default settings...") + start_time = datetime.datetime.now().strftime( fmt ) + run_tests( args.ITERATIONS, args.ITERATIONS_LARGE ) + parse_and_store_results_all( test_db, result_db, args.PLATFORM, start_time, 0, 0 ) + + print("Running the tests with MARS ON...") + enable_mars() + start_time = datetime.datetime.now().strftime( fmt ) + run_tests( args.ITERATIONS, args.ITERATIONS_LARGE ) + parse_and_store_results_all( test_db, result_db, args.PLATFORM, start_time, 1, 0 ) + disable_mars() + + + print("Running the tests with Pooling ON...") + enable_pooling() + start_time = datetime.datetime.now().strftime( fmt ) + run_tests( args.ITERATIONS, args.ITERATIONS_LARGE ) + parse_and_store_results_all( test_db, result_db, args.PLATFORM, start_time, 0, 1 ) + disable_pooling() + + \ No newline at end of file From e250baf57b4c5b2bd1afdc89da13f770084f005c Mon Sep 17 00:00:00 2001 From: ulvii Date: Mon, 19 Jun 2017 14:32:24 -0700 Subject: [PATCH 22/48] Adding pyodbc install instructions to setup scripts --- test/Performance/setup_env_unix.sh | 32 ++++++++++++++++++++++---- test/Performance/setup_env_windows.ps1 | 6 +++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/test/Performance/setup_env_unix.sh b/test/Performance/setup_env_unix.sh index d9a75a84..f32230a2 100644 --- a/test/Performance/setup_env_unix.sh +++ b/test/Performance/setup_env_unix.sh @@ -27,9 +27,12 @@ fi rm -rf env_setup.log touch env_setup.log if [ $PLATFORM = "Ubuntu16" ]; then - echo "Installing git, libxml, autoconf, openssl..." - yes | sudo apt-get install git autoconf libxml2-dev libssl-dev pkg-config >> env_setup.log 2>&1 - + echo "Installing git, libxml, autoconf, openssl, python3, pip3..." + yes | sudo apt-get install git autoconf libxml2-dev libssl-dev pkg-config python3 python3-pip >> env_setup.log 2>&1 + echo "OK" + echo "Installing pyodbc" + pip3 install --upgrade pip >> env_setup.log 2>&1 + pip3 install pyodbc >> env_setup.log 2>&1 echo "OK" echo "Installing MSODBCSQL..." curl -s https://packages.microsoft.com/keys/microsoft.asc | apt-key add - @@ -38,8 +41,21 @@ if [ $PLATFORM = "Ubuntu16" ]; then yes | sudo ACCEPT_EULA=Y apt-get install msodbcsql >> env_setup.log 2>&1 yes | sudo apt-get install -qq unixodbc-dev >> env_setup.log 2>&1 elif [ $PLATFORM = "RedHat7" ]; then - echo "Installing gcc, git, libxml, openssl..." - yes | sudo yum install -y gcc-c++ libxml2-devel git openssl-devel >> env_setup.log 2>&1 + echo "Enabling EPEL repo" + yes | sudo yum install epel-release >> env_setup.log 2>&1 + echo "OK" + echo "Installing python34-setuptools..." + yes | sudo yum install python34-setuptools >> env_setup.log 2>&1 + echo "OK" + echo "Installing gcc, git, libxml, openssl, EPEL, python3, pip3..." + yes | sudo yum install -y gcc-c++ libxml2-devel git openssl-devel python34 >> env_setup.log 2>&1 + echo "OK" + echo "Installing pip3" + yes | sudo easy_install-3.4 pip >> env_setup.log 2>&1 + echo "OK" + echo "Installing pyodbc" + pip3 install --upgrade pip >> env_setup.log 2>&1 + pip3 install pyodbc >> env_setup.log 2>&1 echo "OK" echo "Installing MSODBCSQL..." curl -s https://packages.microsoft.com/config/rhel/7/prod.repo > /etc/yum.repos.d/mssql-release.repo @@ -60,6 +76,12 @@ elif [ $PLATFORM = "Sierra" ]; then brew install pkg-config >> env_setup.log 2>&1 brew install openssl >> env_setup.log 2>&1 echo "OK" + echo "Installing python3..." + brew install python3 >> env_setup.log 2>&1 + echo "OK" + echo "Installing pyodbc..." + pip3 install pyodbc >> env_setup.log 2>&1 + echo "OK" echo "Installing MSODBCSQL..." brew tap microsoft/msodbcsql https://github.com/Microsoft/homebrew-msodbcsql >> env_setup.log 2>&1 brew update >> env_setup.log 2>&1 diff --git a/test/Performance/setup_env_windows.ps1 b/test/Performance/setup_env_windows.ps1 index 3fa72aa1..be52b74b 100644 --- a/test/Performance/setup_env_windows.ps1 +++ b/test/Performance/setup_env_windows.ps1 @@ -21,6 +21,12 @@ Write-Host "Downloading Git..." (New-Object System.Net.WebClient).DownloadFile('https://github.com/git-for-windows/git/releases/download/v2.13.0.windows.1/Git-2.13.0-64-bit.exe', "$tempFolder\git.exe") Write-Host "Installing Git..." .\temp\git.exe /SILENT | Out-Null +Write-Host "Downloading Python3..." +(New-Object System.Net.WebClient).DownloadFile('https://www.python.org/ftp/python/3.6.0/python-3.6.0-amd64.exe', "$tempFolder\python.exe") +Write-Host "Installing Python3..." +.\temp\python.exe /quiet InstallAllUsers=1 PrependPath=1 Include_test=0 | Out-Null +Write-Host "Installing pyodbc..." +pip3 install pyodbc | Out-Null Write-Host "Downloading MSODBCSQL..." (New-object System.Net.WebClient).DownloadFile('https://download.microsoft.com/download/D/5/E/D5EEF288-A277-45C8-855B-8E2CB7E25B96/x64/msodbcsql.msi', "$tempFolder\msodbcsql.msi") Write-Host "Installing MSODBCSQL..." From 38d01dcade69aa89e97760eb61ec91963dfaebea Mon Sep 17 00:00:00 2001 From: ulvii Date: Tue, 20 Jun 2017 17:40:54 -0700 Subject: [PATCH 23/48] Report duration in seconds --- test/Performance/run-perf_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Performance/run-perf_tests.py b/test/Performance/run-perf_tests.py index 37a41091..6f733ebf 100644 --- a/test/Performance/run-perf_tests.py +++ b/test/Performance/run-perf_tests.py @@ -279,7 +279,7 @@ def parse_results( dump_file ): xml_result.error_message = errors[0].text else: xml_result.success = 1 - xml_result.duration = benchmark[0][0].find( 'stats' ).get( 'sum' ) + xml_result.duration = int( round( int( benchmark[0][0].find( 'stats' ).get( 'sum' )) / 1000000 )) memory_peak = 0 for iteration in benchmark[0][0].findall( 'iteration' ): iter_memory_peak = int( iteration.get( 'mem-peak' )) From 40d87aa38f098963338d4550dcec4bc1bd24659f Mon Sep 17 00:00:00 2001 From: ulvii Date: Wed, 21 Jun 2017 18:41:05 -0700 Subject: [PATCH 24/48] run-perf_tests.py: Adding a function to generate SHA1 signature for drivers --- test/Performance/run-perf_tests.py | 78 ++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 15 deletions(-) diff --git a/test/Performance/run-perf_tests.py b/test/Performance/run-perf_tests.py index 6f733ebf..a942d7aa 100644 --- a/test/Performance/run-perf_tests.py +++ b/test/Performance/run-perf_tests.py @@ -12,7 +12,9 @@ import pyodbc import platform import re import datetime +import time from time import strftime +import hashlib sqlsrv_regular_path = "benchmark"+ os.sep + "sqlsrv" + os.sep + "regular" sqlsrv_large_path = "benchmark"+ os.sep + "sqlsrv" + os.sep + "large" @@ -20,6 +22,7 @@ pdo_regular_path = "benchmark"+ os.sep + "pdo_sqlsrv" + os.sep + "regular" pdo_large_path = "benchmark"+ os.sep + "pdo_sqlsrv" + os.sep + "large" connect_file = "lib" + os.sep + "connect.php" connect_file_bak = connect_file + ".bak" +fmt = "%Y-%m-%d %H:%M:%S.0000000" def validate_platform( platform_name ): platforms = [ @@ -83,10 +86,20 @@ def get_run_command( path_to_tests, iterations, dump_file ): command = "vendor/bin/phpbench run {0} --iterations {1} --dump-file={2}" return command.format( path_to_tests, iterations, dump_file ) -def get_id( conn, id_field, table, name_field, name): +def get_id( conn, id_field, table, name_field, value ): query = "SELECT {0} FROM {1} WHERE {2}='{3}'" cursor = conn.cursor() - cursor.execute( query.format( id_field, table, name_field, name )) + cursor.execute( query.format( id_field, table, name_field, value )) + id = cursor.fetchone() + cursor.close() + if id is not None: + return id[0] + return id + +def get_id_no_quote( conn, id_field, table, name_field, value ): + query = "SELECT {0} FROM {1} WHERE {2}={3}" + cursor = conn.cursor() + cursor.execute( query.format( id_field, table, name_field, value )) id = cursor.fetchone() cursor.close() if id is not None: @@ -122,6 +135,17 @@ def get_server_version( server): version = cursor.fetchone()[0] cursor.close() return version + +def get_sha1_file( filename ): + hash_size = 256 + sha1 = hashlib.sha1() + with open( filename, 'rb' ) as f: + while True: + data = f.read( hash_size ) + if not data: + break + sha1.update( data ) + return "0x" + sha1.hexdigest() def insert_server_entry( conn, server_name, server_version ): query = "INSERT INTO Servers ( HostName, Version ) VALUES ( '{0}', '{1}' )" @@ -148,6 +172,13 @@ def insert_test_entry( conn, name ): cursor.execute( query.format( name )) cursor.close() +def insert_driver_entry( conn, driver_path, driver_hash ): + file_date = time.strftime( fmt, time.gmtime( os.path.getmtime( driver_path ))) + query = "INSERT INTO Drivers ( Arch, FileDate, SHA1, HashVer ) VALUES ( ?, ?, {0}, 1 )" + cursor = conn.cursor() + cursor.execute( query.format(driver_hash), ( get_php_arch(), file_date )) + cursor.close() + def get_server_id( conn, test_db ): server_id = get_id( conn, "ServerId", "Servers", "HostName", test_db.server_name ) if server_id is None: @@ -177,7 +208,16 @@ def get_test_id( conn, test_name ): insert_test_entry( conn, test_name ) test_id = get_id( conn, "TestId", "PerformanceTests", "TestName", test_name ) return test_id - + +def get_driver_id( conn, driver_name ): + driver_path = get_path_to_driver( driver_name ) + driver_hash = get_sha1_file( driver_path ) + driver_id = get_id_no_quote( conn, "DriverId", "Drivers", "SHA1", driver_hash ) + if driver_id is None: + insert_driver_entry( conn, driver_path, driver_hash ) + driver_id = get_id_no_quote( conn, "DriverId", "Drivers", "SHA1", driver_hash ) + return driver_id + def insert_result_entry_and_get_id( conn, test_id, client_id, driver_id, server_id, team_id, success ): query = "INSERT INTO PerformanceResults( TestId, ClientId, DriverId, ServerId, TeamId, Success ) OUTPUT INSERTED.ResultId VALUES( {0}, {1}, {2}, {3}, {4}, {5} )" cursor = conn.cursor() @@ -214,6 +254,15 @@ def get_php_thread(): else: return "ts" +def get_path_to_driver( driver_name ): + p = subprocess.Popen( "php -r \"echo ini_get('extension_dir');\"", stdout=subprocess.PIPE, shell = True ) + out, err = p.communicate() + extension_dir = out.decode('ascii') + if os.name == 'nt': + return extension_dir + os.sep + "php_" + driver_name + ".dll" + else: + return extension_dir + os.sep + driver_name + ".so" + def enable_mars(): print( "Enabling MARS...") with fileinput.FileInput( connect_file, inplace=True, backup='.bak') as file: @@ -290,22 +339,22 @@ def parse_results( dump_file ): return xml_results def parse_and_store_results( dump_file, test_db, result_db, platform, driver, start_time, mars, pooling ): + conn = connect( result_db ) server_id = get_server_id( conn, test_db ) client_id = get_client_id( conn ) - team_id = get_team_id( conn ) - # TO - DO Add a function to insert a driver entry - driver_id=1 + team_id = get_team_id( conn ) + driver_id = get_driver_id( conn, driver ) - arch = get_php_arch() - thread = get_php_thread() - cursor = conn.cursor() + arch = get_php_arch() + thread = get_php_thread() + cursor = conn.cursor() results = parse_results( dump_file ) for result in results: test_name = get_test_name( result.benchmark_name ) - test_id = get_test_id( conn, test_name ) + test_id = get_test_id( conn, test_name ) result_id = insert_result_entry_and_get_id( conn, test_id, client_id, driver_id, server_id, team_id, result.success ) if result.success: @@ -340,19 +389,20 @@ if __name__ == '__main__': parser.add_argument( '-result-pwd', '--RESULT_PWD', required=True ) args = parser.parse_args() + start_time = datetime.datetime.now().strftime( fmt ) + print( "Start time: " + start_time ) + validate_platform( args.PLATFORM ) result_db = DB( args.RESULT_SERVER, args.RESULT_DB, args.RESULT_UID, args.RESULT_PWD ) test_db = get_test_database() - fmt = "%Y-%m-%d %H:%M:%S.0000000" print("Running the tests with default settings...") - start_time = datetime.datetime.now().strftime( fmt ) + run_tests( args.ITERATIONS, args.ITERATIONS_LARGE ) parse_and_store_results_all( test_db, result_db, args.PLATFORM, start_time, 0, 0 ) print("Running the tests with MARS ON...") enable_mars() - start_time = datetime.datetime.now().strftime( fmt ) run_tests( args.ITERATIONS, args.ITERATIONS_LARGE ) parse_and_store_results_all( test_db, result_db, args.PLATFORM, start_time, 1, 0 ) disable_mars() @@ -360,9 +410,7 @@ if __name__ == '__main__': print("Running the tests with Pooling ON...") enable_pooling() - start_time = datetime.datetime.now().strftime( fmt ) run_tests( args.ITERATIONS, args.ITERATIONS_LARGE ) parse_and_store_results_all( test_db, result_db, args.PLATFORM, start_time, 0, 1 ) disable_pooling() - \ No newline at end of file From de5c9ebb3648b0059628e73ee6002da4e86f75d2 Mon Sep 17 00:00:00 2001 From: ulvii Date: Thu, 22 Jun 2017 13:21:02 -0700 Subject: [PATCH 25/48] Update README.md Updating Performance test readme file with instructions how to run the tests --- test/Performance/README.md | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/test/Performance/README.md b/test/Performance/README.md index 8faf63a8..151d2eb2 100644 --- a/test/Performance/README.md +++ b/test/Performance/README.md @@ -5,7 +5,10 @@ Install Visual Studio 2015 before running the following commands. Make sure C++ Run `cmd` as administrator. powershell - .\setup_env_windows.ps1 + Set-ExecutionPolicy Unrestricted + .\setup_env_windows.ps1 +If `PHP_VERSION` is wrong, the script will default it to the latest PHP 7.1 version + ### Ubuntu 16 sudo env “PATH=$PATH” bash setup_env_unix.sh Ubuntu16 ### RedHat 7 @@ -14,17 +17,21 @@ Run `cmd` as administrator. `brew` cannot be run with `sudo` on Sierra. Either enable passwordless `sudo` on the machine or enter the password when prompted. bash setup_env_unix.sh Sierra -## Run benchmarks - Subject to change once the process is automated +## Run benchmarks -Run sqlsrv benchmarks: +### 1. Modify lib/connect.php with the test database credetials +### 2. Execute run-perf_tests.py. +The script must be executed with `sudo` because to enable pooling it needs to modify odbcinst.ini system file. As an improvement, the location of the odbcinst.ini file can be changed so that, sudo is not requiered. + + run-perf_tests.py -platform -iterations -iterations-large -result-server -result-db -result-uid -result-pwd + +`-platform` - The platform that the tests are ran on. Must be one of the following: Windows10, WidnowsServer2016 WindowsServer2012 Ubuntu16 RedHat7 Sierra +`-iterations` - The number of iterations for regular tests. +`-iterations-large` - The number of iterations for the tests that fetch large data. Usually set to 1. +`-result-server` - The server of result database. It is assumed that, the result database already setup before running the tests. +`-result-db` - Database name. With the current result database setup files, this should be set to `TestResults` +`-result-uid` - Result database username +`-result-pwd` Result database password - ./vendor/bin/phpbench run benchmark/sqlsrv/regular --time-unit="milliseconds" --iterations [num_of_iterations] --report=aggregate - -Run pdo_sqlsrv benchmarks: - ./vendor/bin/phpbench run benchmark/pdo_sqlsrv/regular --time-unit="milliseconds" --iterations [num_of_iterations] --report=aggregate -Run benchmarks that fetch large dataset. These benchmarks assume the database is already populated with data. - - ./vendor/bin/phpbench run benchmark/sqlsrv/large --time-unit="milliseconds" --report=aggregate - ./vendor/bin/phpbench run benchmark/pdo_sqlsrv/large --time-unit="milliseconds" --report=aggregate From bb385590b15f8a8f19a95bf8e4578c4413cdc057 Mon Sep 17 00:00:00 2001 From: ulvii Date: Thu, 22 Jun 2017 13:22:37 -0700 Subject: [PATCH 26/48] Addressing review comments. Adding a few checks to windows setup file --- .../regular/SqlsrvCreateDbTableProcBench.php | 2 +- test/Performance/lib/SqlsrvUtil.php | 5 ++- test/Performance/setup_env_windows.ps1 | 39 ++++++++++++++++--- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/test/Performance/benchmark/sqlsrv/regular/SqlsrvCreateDbTableProcBench.php b/test/Performance/benchmark/sqlsrv/regular/SqlsrvCreateDbTableProcBench.php index a3495ee9..8952f724 100644 --- a/test/Performance/benchmark/sqlsrv/regular/SqlsrvCreateDbTableProcBench.php +++ b/test/Performance/benchmark/sqlsrv/regular/SqlsrvCreateDbTableProcBench.php @@ -14,7 +14,7 @@ class SqlsrvCreateDbTableProcBench{ /* * Each iteration creates a database, a table and a stored procedure in that database and drops the database at the end. - * Not that, execDirect function are used to execute all the queries. + * Note that, ODBC SQLExecDirect function are used to execute all the queries. */ public function benchCreateDbTableProc(){ $randomNum = rand(); diff --git a/test/Performance/lib/SqlsrvUtil.php b/test/Performance/lib/SqlsrvUtil.php index fc66726a..f2a73533 100644 --- a/test/Performance/lib/SqlsrvUtil.php +++ b/test/Performance/lib/SqlsrvUtil.php @@ -18,7 +18,10 @@ class SqlsrvUtil{ if ( $conn === false || $conn === null ){ die( print_r( "Invalid connection resource\n")); } - sqlsrv_close( $conn ); + $ret = sqlsrv_close( $conn ); + if ( $ret === false ){ + die( print_r( sqlsrv_errors(), true)); + } } public static function selectVersion( $conn ){ diff --git a/test/Performance/setup_env_windows.ps1 b/test/Performance/setup_env_windows.ps1 index be52b74b..f1efbd21 100644 --- a/test/Performance/setup_env_windows.ps1 +++ b/test/Performance/setup_env_windows.ps1 @@ -9,18 +9,47 @@ Param( [string]$ARCH ) -$PHP_VERSION_MINOR=$PHP_VERSION.split(".")[1] +function Get-UrlStatusCode([string] $Url) +{ + try + { + (Invoke-WebRequest -Uri $Url -UseBasicParsing -DisableKeepAlive).StatusCode + } + catch [Net.WebException] + { + [int]$_.Exception.Response.StatusCode + } +} + +IF($ARCH -ne "x64" -And $ARCH -ne "x86"){ + Write-Host "ARCH must either x64 or x86" + Break +} + +IF($PHP_THREAD -ne "nts" -And $PHP_THREAD -ne "ts"){ + Write-Host "PHP_THREAD must either nts or ts" + Break +} + $startingDir=$pwd.Path $tempFolder=Join-Path $startingDir "temp" - Remove-Item temp -Recurse -Force -ErrorAction Ignore New-Item -ItemType directory -Path temp -Write-Host "Downloading Git..." -(New-Object System.Net.WebClient).DownloadFile('https://github.com/git-for-windows/git/releases/download/v2.13.0.windows.1/Git-2.13.0-64-bit.exe', "$tempFolder\git.exe") +(New-Object System.Net.WebClient).DownloadFile('http://windows.php.net/downloads/releases/sha1sum.txt',"$tempFolder\sha1sum.txt") +$PHP70_LATEST_VERSION=type $tempFolder\sha1sum.txt | where { $_ -match "php-(7.0\.\d+)-src" } | foreach { $matches[1] } +$PHP71_LATEST_VERSION=type $tempFolder\sha1sum.txt | where { $_ -match "php-(7.1\.\d+)-src" } | foreach { $matches[1] } +#check if PHP_VERSION source exisits +$statusCode = Get-UrlStatusCode "http://windows.php.net/downloads/releases/php-$PHP_VERSION-src.zip" +#If provided php version source does not exists, default the version to latest php 71 source +IF($statusCode -eq 404){$PHP_VERSION=$PHP71_LATEST_VERSION} +$PHP_VERSION_MINOR=$PHP_VERSION.split(".")[1] + +Write-Host "Installing chocolatey..." +iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) Write-Host "Installing Git..." -.\temp\git.exe /SILENT | Out-Null +choco install git Write-Host "Downloading Python3..." (New-Object System.Net.WebClient).DownloadFile('https://www.python.org/ftp/python/3.6.0/python-3.6.0-amd64.exe', "$tempFolder\python.exe") Write-Host "Installing Python3..." From 1e3c1c8dcc0b5049f0db73aa22b0a1c296166c3c Mon Sep 17 00:00:00 2001 From: ulvii Date: Wed, 28 Jun 2017 17:54:18 -0700 Subject: [PATCH 27/48] Adding a few more functions to get php version, driver version, msodbcsql version --- test/Performance/run-perf_tests.py | 148 ++++++++++++++++++----------- 1 file changed, 90 insertions(+), 58 deletions(-) diff --git a/test/Performance/run-perf_tests.py b/test/Performance/run-perf_tests.py index a942d7aa..23e2f1aa 100644 --- a/test/Performance/run-perf_tests.py +++ b/test/Performance/run-perf_tests.py @@ -23,7 +23,7 @@ pdo_large_path = "benchmark"+ os.sep + "pdo_sqlsrv" + os.sep + "large" connect_file = "lib" + os.sep + "connect.php" connect_file_bak = connect_file + ".bak" fmt = "%Y-%m-%d %H:%M:%S.0000000" - + def validate_platform( platform_name ): platforms = [ "Windows10" @@ -36,7 +36,7 @@ def validate_platform( platform_name ): print ( "Platform must be one of the following:" ) print( platforms ) exit( 1 ) - + class DB( object ): def __init__ ( self , server_name = None @@ -54,13 +54,15 @@ class XMLResult( object ): , success = None , duration = None , memory = None + , iterations = None , error_message = None ): self.benchmark_name = benchmark_name self.success = success self.duration = duration self.memory = memory + self.iterations = iterations self.error_message = error_message - + def get_test_name( name ): test_name_dict = { 'SqlsrvConnectionBench': 'connection' @@ -85,7 +87,7 @@ def get_test_name( name ): def get_run_command( path_to_tests, iterations, dump_file ): command = "vendor/bin/phpbench run {0} --iterations {1} --dump-file={2}" return command.format( path_to_tests, iterations, dump_file ) - + def get_id( conn, id_field, table, name_field, value ): query = "SELECT {0} FROM {1} WHERE {2}='{3}'" cursor = conn.cursor() @@ -95,7 +97,7 @@ def get_id( conn, id_field, table, name_field, value ): if id is not None: return id[0] return id - + def get_id_no_quote( conn, id_field, table, name_field, value ): query = "SELECT {0} FROM {1} WHERE {2}={3}" cursor = conn.cursor() @@ -105,7 +107,7 @@ def get_id_no_quote( conn, id_field, table, name_field, value ): if id is not None: return id[0] return id - + def get_test_database(): test_db = DB() for line in open( connect_file ): @@ -118,7 +120,7 @@ def get_test_database(): elif "pwd" in line: test_db.password = line.split("=")[1].strip()[1:-2] return test_db - + def connect( db ): return pyodbc.connect( driver="{ODBC Driver 13 for SQL Server}" @@ -127,7 +129,7 @@ def connect( db ): , user=db.username , password=db.password , autocommit = True) - + def get_server_version( server): conn = connect( server ) cursor = conn.cursor() @@ -135,7 +137,7 @@ def get_server_version( server): version = cursor.fetchone()[0] cursor.close() return version - + def get_sha1_file( filename ): hash_size = 256 sha1 = hashlib.sha1() @@ -152,40 +154,40 @@ def insert_server_entry( conn, server_name, server_version ): cursor = conn.cursor() cursor.execute( query.format( server_name, server_version )) cursor.close() - + def insert_client_entry ( conn, name ): query = "INSERT INTO Clients ( HostName ) VALUES( '{0}' )" cursor = conn.cursor() cursor.execute( query.format( name )) cursor.close() - + def insert_team_entry ( conn, name ): query = "INSERT INTO Teams ( TeamName ) VALUES( '{0}' )" cursor = conn.cursor() cursor.execute( query.format( name )) cursor.close() - + def insert_test_entry( conn, name ): #TO-DO Remove unnecessary columns from the table and fix the query string. Amd64 and 0 are used to bypass not null query = "INSERT INTO PerformanceTests ( TestName, Arch, HashVer ) VALUES( '{0}', 'Amd64', 0 )" cursor = conn.cursor() cursor.execute( query.format( name )) cursor.close() - + def insert_driver_entry( conn, driver_path, driver_hash ): file_date = time.strftime( fmt, time.gmtime( os.path.getmtime( driver_path ))) query = "INSERT INTO Drivers ( Arch, FileDate, SHA1, HashVer ) VALUES ( ?, ?, {0}, 1 )" cursor = conn.cursor() cursor.execute( query.format(driver_hash), ( get_php_arch(), file_date )) cursor.close() - + def get_server_id( conn, test_db ): server_id = get_id( conn, "ServerId", "Servers", "HostName", test_db.server_name ) if server_id is None: insert_server_entry( conn, test_db.server_name, get_server_version( test_db )) server_id = get_id( conn, "ServerId", "Servers", "HostName", test_db.server_name ) return server_id - + def get_client_id( conn ): client_name = platform.node() client_id = get_id( conn, "ClientId", "Clients", "HostName", client_name ) @@ -193,7 +195,7 @@ def get_client_id( conn ): insert_client_entry( conn, client_name ) client_id = get_id( conn, "ClientId", "Clients", "HostName", client_name ) return client_id - + def get_team_id( conn ): team_name = "PHP" team_id = get_id( conn, "TeamId", "Teams", "TeamName", team_name) @@ -201,14 +203,14 @@ def get_team_id( conn ): insert_team_entry( conn, team_name ) team_id = get_id( conn, "TeamId", "Teams", "TeamName", team_name) return team_id - + def get_test_id( conn, test_name ): test_id = get_id( conn, "TestId", "PerformanceTests", "TestName", test_name ) if test_id is None: insert_test_entry( conn, test_name ) test_id = get_id( conn, "TestId", "PerformanceTests", "TestName", test_name ) return test_id - + def get_driver_id( conn, driver_name ): driver_path = get_path_to_driver( driver_name ) driver_hash = get_sha1_file( driver_path ) @@ -227,13 +229,13 @@ def insert_result_entry_and_get_id( conn, test_id, client_id, driver_id, server_ if result_id is not None: return result_id[0] return id - + def insert_key_value( conn, table_name, result_id, key, value ): query = "INSERT INTO {0} ( ResultId, name, value ) VALUES( ?, ?, ? )" cursor = conn.cursor() cursor.execute( query.format( table_name ), ( result_id, key, value ) ) cursor.close() - + def get_php_arch(): p = subprocess.Popen( "php -r 'echo PHP_INT_SIZE;'", stdout=subprocess.PIPE, shell = True ) out, err = p.communicate() @@ -241,7 +243,12 @@ def get_php_arch(): return "x64" elif out.decode('ascii') == "4": return "x86" - + +def get_php_version(): + p = subprocess.Popen( "php -r 'echo phpversion();'", stdout=subprocess.PIPE, shell = True ) + out, err = p.communicate() + return out.decode('ascii') + def get_php_thread(): if os.name == 'nt': command = "php -i | findstr 'Thread'" @@ -253,7 +260,20 @@ def get_php_thread(): return "nts" else: return "ts" - + +def get_driver_version( driver_name ): + command = "php -r \"echo phpversion('{0}');\"" + print(command.format( driver_name )) + p = subprocess.Popen( command.format( driver_name ), stdout=subprocess.PIPE, shell = True ) + out, err = p.communicate() + return out.decode('ascii') + +def get_msodbcsql_version( test_db ): + command = "php -r \"echo sqlsrv_client_info( sqlsrv_connect( '{0}', array( 'UID'=>'{1}', 'PWD'=>'{2}')))['DriverName'];\"" + p = subprocess.Popen( command.format( test_db.server_name, test_db.username, test_db.password ), stdout=subprocess.PIPE, shell = True ) + out, err = p.communicate() + return out.decode('ascii') + def get_path_to_driver( driver_name ): p = subprocess.Popen( "php -r \"echo ini_get('extension_dir');\"", stdout=subprocess.PIPE, shell = True ) out, err = p.communicate() @@ -262,18 +282,18 @@ def get_path_to_driver( driver_name ): return extension_dir + os.sep + "php_" + driver_name + ".dll" else: return extension_dir + os.sep + driver_name + ".so" - + def enable_mars(): print( "Enabling MARS...") with fileinput.FileInput( connect_file, inplace=True, backup='.bak') as file: for line in file: print( line.replace( "$mars=false;", "$mars=true;" ), end='') - + def disable_mars(): print( "Disabling MARS...") os.remove( connect_file ) copyfile( connect_file_bak, connect_file ) - + def enable_pooling(): print( "Enabling Pooling...") if os.name == 'nt': @@ -293,7 +313,7 @@ def enable_pooling(): with open( odbcinst, "a" ) as f: f.write( lines_to_append ) - + def disable_pooling(): print("Disabling Pooling...") if os.name == 'nt': @@ -306,20 +326,21 @@ def disable_pooling(): os.remove( odbcinst ) copyfile( odbcinst_bak, odbcinst ) os.remove( odbcinst_bak ) - + def run_tests( iterations, iterations_large ): print("Running the tests...") - call( get_run_command( sqlsrv_regular_path, iterations, "sqlsrv-regular.xml" ), shell=True, stdout=open( os.devnull, 'wb' )) - call( get_run_command( sqlsrv_large_path, iterations_large, "sqlsrv-large.xml" ), shell=True, stdout=open( os.devnull, 'wb' )) + call( get_run_command( sqlsrv_regular_path, iterations, "sqlsrv-regular.xml" ), shell=True ) + call( get_run_command( sqlsrv_large_path, iterations_large, "sqlsrv-large.xml" ), shell=True ) + + call( get_run_command( pdo_regular_path, iterations, "pdo_sqlsrv-regular.xml" ), shell=True ) + call( get_run_command( pdo_large_path, iterations_large, "pdo_sqlsrv-large.xml" ), shell=True ) - call( get_run_command( pdo_regular_path, iterations, "pdo_sqlsrv-regular.xml" ), shell=True, stdout=open( os.devnull, 'wb' )) - call( get_run_command( pdo_large_path, iterations_large, "pdo_sqlsrv-large.xml" ), shell=True, stdout=open( os.devnull, 'wb' )) - def parse_results( dump_file ): xml_results = [] tree = ET.parse( dump_file ) root = tree.getroot() - for benchmark in root[0].findall( 'benchmark' ): + benchmarks = root[0].findall( 'benchmark' ) + for benchmark in benchmarks: xml_result = XMLResult() xml_result.benchmark_name = benchmark.get( 'class' )[1:] errors = benchmark[0][0].find( 'errors' ) @@ -329,55 +350,65 @@ def parse_results( dump_file ): else: xml_result.success = 1 xml_result.duration = int( round( int( benchmark[0][0].find( 'stats' ).get( 'sum' )) / 1000000 )) + iterations = benchmark[0][0].findall( 'iteration' ) + xml_result.iterations = len( iterations ) memory_peak = 0 - for iteration in benchmark[0][0].findall( 'iteration' ): + for iteration in iterations: iter_memory_peak = int( iteration.get( 'mem-peak' )) if iter_memory_peak > memory_peak: memory_peak = iter_memory_peak xml_result.memory = memory_peak xml_results.append( xml_result ) return xml_results - + def parse_and_store_results( dump_file, test_db, result_db, platform, driver, start_time, mars, pooling ): - + conn = connect( result_db ) - + server_id = get_server_id( conn, test_db ) client_id = get_client_id( conn ) team_id = get_team_id( conn ) driver_id = get_driver_id( conn, driver ) + - arch = get_php_arch() - thread = get_php_thread() + php_arch = get_php_arch() + php_thread = get_php_thread() + php_version = get_php_version() + driver_version = get_driver_version( driver ) + msodbcsql_version = get_msodbcsql_version( test_db ) + cursor = conn.cursor() results = parse_results( dump_file ) - + for result in results: test_name = get_test_name( result.benchmark_name ) test_id = get_test_id( conn, test_name ) result_id = insert_result_entry_and_get_id( conn, test_id, client_id, driver_id, server_id, team_id, result.success ) - + if result.success: - insert_key_value( conn, "KeyValueTableBigInt", result_id, "duration", result.duration ) - insert_key_value( conn, "KeyValueTableBigInt", result_id, "memory", result.memory ) + insert_key_value( conn, "KeyValueTableBigInt", result_id, "duration", result.duration ) + insert_key_value( conn, "KeyValueTableBigInt", result_id, "memory", result.memory ) + insert_key_value( conn, "KeyValueTableBigInt", result_id, "iterations", result.iterations) else: insert_key_value( conn, "KeyValueTableString", result_id, "error", result.error_message ) - - insert_key_value( conn, "KeyValueTableDate" , result_id, "startTime", start_time ) - insert_key_value( conn, "KeyValueTableBigInt", result_id, "mars" , mars ) - insert_key_value( conn, "KeyValueTableBigInt", result_id, "pooling" , pooling ) - insert_key_value( conn, "KeyValueTableString", result_id, "driver" , driver ) - insert_key_value( conn, "KeyValueTableString", result_id, "arch" , arch ) - insert_key_value( conn, "KeyValueTableString", result_id, "os" , platform ) - insert_key_value( conn, "KeyValueTableString", result_id, "thread" , thread ) - + + insert_key_value( conn, "KeyValueTableDate" , result_id, "startTime" , start_time ) + insert_key_value( conn, "KeyValueTableBigInt", result_id, "mars" , mars ) + insert_key_value( conn, "KeyValueTableBigInt", result_id, "pooling" , pooling ) + insert_key_value( conn, "KeyValueTableString", result_id, "driver" , driver ) + insert_key_value( conn, "KeyValueTableString", result_id, "php_arch" , php_arch ) + insert_key_value( conn, "KeyValueTableString", result_id, "os" , platform ) + insert_key_value( conn, "KeyValueTableString", result_id, "php_thread" , php_thread ) + insert_key_value( conn, "KeyValueTableString", result_id, "php_version", php_version ) + insert_key_value( conn, "KeyValueTableString", result_id, "msodbcsql" , msodbcsql_version ) + def parse_and_store_results_all( test_db, result_db, platform, start_time, mars, pooling ): print("Parsing and storing the results...") parse_and_store_results( "sqlsrv-regular.xml", test_db, result_db, platform, "sqlsrv", start_time, mars, pooling ) parse_and_store_results( "sqlsrv-large.xml", test_db, result_db, platform, "sqlsrv", start_time, mars, pooling ) parse_and_store_results( "pdo_sqlsrv-regular.xml", test_db, result_db, platform, "pdo_sqlsrv", start_time, mars, pooling ) parse_and_store_results( "pdo_sqlsrv-large.xml", test_db, result_db, platform, "pdo_sqlsrv", start_time, mars, pooling ) - + if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument( '-platform', '--PLATFORM', required=True ) @@ -388,16 +419,16 @@ if __name__ == '__main__': parser.add_argument( '-result-uid', '--RESULT_UID', required=True ) parser.add_argument( '-result-pwd', '--RESULT_PWD', required=True ) args = parser.parse_args() - + start_time = datetime.datetime.now().strftime( fmt ) print( "Start time: " + start_time ) - + validate_platform( args.PLATFORM ) result_db = DB( args.RESULT_SERVER, args.RESULT_DB, args.RESULT_UID, args.RESULT_PWD ) test_db = get_test_database() - + print("Running the tests with default settings...") - + run_tests( args.ITERATIONS, args.ITERATIONS_LARGE ) parse_and_store_results_all( test_db, result_db, args.PLATFORM, start_time, 0, 0 ) @@ -406,11 +437,12 @@ if __name__ == '__main__': run_tests( args.ITERATIONS, args.ITERATIONS_LARGE ) parse_and_store_results_all( test_db, result_db, args.PLATFORM, start_time, 1, 0 ) disable_mars() - + print("Running the tests with Pooling ON...") enable_pooling() run_tests( args.ITERATIONS, args.ITERATIONS_LARGE ) parse_and_store_results_all( test_db, result_db, args.PLATFORM, start_time, 0, 1 ) disable_pooling() + \ No newline at end of file From 0793c9a92260e14414adc44a0a72cb060072a176 Mon Sep 17 00:00:00 2001 From: ulvii Date: Wed, 28 Jun 2017 17:55:27 -0700 Subject: [PATCH 28/48] Adding curl installation. Also making sure unixodbc is installed before install pyodbc --- test/Performance/setup_env_unix.sh | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/Performance/setup_env_unix.sh b/test/Performance/setup_env_unix.sh index f32230a2..3b8f9f2a 100644 --- a/test/Performance/setup_env_unix.sh +++ b/test/Performance/setup_env_unix.sh @@ -27,12 +27,8 @@ fi rm -rf env_setup.log touch env_setup.log if [ $PLATFORM = "Ubuntu16" ]; then - echo "Installing git, libxml, autoconf, openssl, python3, pip3..." - yes | sudo apt-get install git autoconf libxml2-dev libssl-dev pkg-config python3 python3-pip >> env_setup.log 2>&1 - echo "OK" - echo "Installing pyodbc" - pip3 install --upgrade pip >> env_setup.log 2>&1 - pip3 install pyodbc >> env_setup.log 2>&1 + echo "Installing git, curl, libxml, autoconf, openssl, python3, pip3..." + yes | sudo apt-get install git curl autoconf libxml2-dev libssl-dev pkg-config python3 python3-pip >> env_setup.log 2>&1 echo "OK" echo "Installing MSODBCSQL..." curl -s https://packages.microsoft.com/keys/microsoft.asc | apt-key add - @@ -40,6 +36,10 @@ if [ $PLATFORM = "Ubuntu16" ]; then yes | sudo apt-get update >> env_setup.log 2>&1 yes | sudo ACCEPT_EULA=Y apt-get install msodbcsql >> env_setup.log 2>&1 yes | sudo apt-get install -qq unixodbc-dev >> env_setup.log 2>&1 + echo "Installing pyodbc" + pip3 install --upgrade pip >> env_setup.log 2>&1 + pip3 install pyodbc >> env_setup.log 2>&1 + echo "OK" elif [ $PLATFORM = "RedHat7" ]; then echo "Enabling EPEL repo" yes | sudo yum install epel-release >> env_setup.log 2>&1 @@ -53,15 +53,15 @@ elif [ $PLATFORM = "RedHat7" ]; then echo "Installing pip3" yes | sudo easy_install-3.4 pip >> env_setup.log 2>&1 echo "OK" - echo "Installing pyodbc" - pip3 install --upgrade pip >> env_setup.log 2>&1 - pip3 install pyodbc >> env_setup.log 2>&1 - echo "OK" echo "Installing MSODBCSQL..." curl -s https://packages.microsoft.com/config/rhel/7/prod.repo > /etc/yum.repos.d/mssql-release.repo (yes | sudo ACCEPT_EULA=Y yum install -y msodbcsql >> env_setup.log 2>&1) (yes | sudo yum install -y unixODBC-devel autoconf >> env_setup.log 2>&1) echo "OK" + echo "Installing pyodbc" + pip3 install --upgrade pip >> env_setup.log 2>&1 + pip3 install pyodbc >> env_setup.log 2>&1 + echo "OK" elif [ $PLATFORM = "Sierra" ]; then echo "Installing homebrew..." yes | /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" >> env_setup.log 2>&1 @@ -79,15 +79,15 @@ elif [ $PLATFORM = "Sierra" ]; then echo "Installing python3..." brew install python3 >> env_setup.log 2>&1 echo "OK" - echo "Installing pyodbc..." - pip3 install pyodbc >> env_setup.log 2>&1 - echo "OK" echo "Installing MSODBCSQL..." brew tap microsoft/msodbcsql https://github.com/Microsoft/homebrew-msodbcsql >> env_setup.log 2>&1 brew update >> env_setup.log 2>&1 yes | ACCEPT_EULA=Y brew install msodbcsql >> env_setup.log 2>&1 echo "OK" yes | brew install autoconf >> env_setup.log 2>&1 + echo "Installing pyodbc..." + pip3 install pyodbc >> env_setup.log 2>&1 + echo "OK" fi echo "Downloading PHP-$PHP_VERSION source tarball..." wget http://ca1.php.net/get/php-$PHP_VERSION.tar.gz/from/this/mirror -O php-$PHP_VERSION.tar.gz >> env_setup.log 2>&1 @@ -122,8 +122,8 @@ echo "extension=$EXTENSION_DIR/pdo_sqlsrv.so" >> php.ini sudo cp php.ini /usr/local/lib cd .. php -v -php --ri sqlsrv -php --ri pdo_sqlsrv +php --ri sqlsrv +php --ri pdo_sqlsrv echo "Installing Composer..." wget https://getcomposer.org/installer -O composer-setup.php >> env_setup.log 2>&1 php composer-setup.php >> env_setup.log 2>&1 From c0aabee4f101dae3e3a07abf42972d368e180a5a Mon Sep 17 00:00:00 2001 From: ulvii Date: Wed, 28 Jun 2017 17:56:02 -0700 Subject: [PATCH 29/48] Adding a basic scripts to report the results --- test/Performance/report.sql | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 test/Performance/report.sql diff --git a/test/Performance/report.sql b/test/Performance/report.sql new file mode 100644 index 00000000..981aa1cc --- /dev/null +++ b/test/Performance/report.sql @@ -0,0 +1,24 @@ +--The script can be run to read the results +select t1.ResultId, Test, Client, Server, Driver, Duration, Memory, Success, Team, StartTime from +( +select pr.ResultId, pr.Success, pt.TestName as Test, cl.HostName as Client, srv.HostName as Server, +tm.TeamName as Team, st.value as Driver, bi.value as Duration, bi2.value as Memory, dt.value as StartTime from +KeyValueTableBigInt bi, +KeyValueTableBigInt bi2, +KeyValueTableString st, +KeyValueTableDate dt, +PerformanceResults pr, +Clients cl, +PerformanceTests pt, +Teams tm, +Servers srv +where bi.name = 'duration' and bi.ResultId = pr.ResultId +and bi2.name = 'memory' and bi2.ResultId = pr.ResultId +and dt.name = 'startTime' and dt.ResultId = pr.ResultId +and st.name = 'driver' and st.ResultId = pr.ResultId +and cl.ClientId = pr.ClientId +and pt.TestId = pr.TestId +and tm.TeamId = pr.TeamId +and srv.ServerId = pr.ServerId +) t1 where StartTime like '%2017-06-23%' + From 224c3651ae7fd039b2cf43fe3e9e11afb853083c Mon Sep 17 00:00:00 2001 From: ulvii Date: Tue, 4 Jul 2017 17:32:38 -0700 Subject: [PATCH 30/48] Started adding documentation to run-pref_test.py --- test/Performance/run-perf_tests.py | 58 ++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/test/Performance/run-perf_tests.py b/test/Performance/run-perf_tests.py index 23e2f1aa..95a8482a 100644 --- a/test/Performance/run-perf_tests.py +++ b/test/Performance/run-perf_tests.py @@ -1,3 +1,11 @@ +#!/usr/bin/python3 +""" + Description: This script intended to run the Performance Tests on Windows, Linux and Mac. + Requirements: + Run setup_env_unix.sh( Linux and Mac ) or setup_env_windows.ps1( Windows ) before invoking this script. + modify lib/connect.php with the credentials to connect to the test database. +""" + import shutil from shutil import copyfile import os @@ -15,16 +23,36 @@ import datetime import time from time import strftime import hashlib - -sqlsrv_regular_path = "benchmark"+ os.sep + "sqlsrv" + os.sep + "regular" -sqlsrv_large_path = "benchmark"+ os.sep + "sqlsrv" + os.sep + "large" -pdo_regular_path = "benchmark"+ os.sep + "pdo_sqlsrv" + os.sep + "regular" -pdo_large_path = "benchmark"+ os.sep + "pdo_sqlsrv" + os.sep + "large" + +""" + Paths to current benchmarks. These constants should be modified if there are any changes in folder structure of the project. "regular" folder contains the benchmarks that can be run for any iterations. "large" folder contains the benchmarks ( currently the benchmark that fetches large amount of data ) that take long time to run and meant to have less number of iterations than the regular ones. +""" + +sqlsrv_regular_path = "benchmark" + os.sep + "sqlsrv" + os.sep + "regular" +sqlsrv_large_path = "benchmark" + os.sep + "sqlsrv" + os.sep + "large" +pdo_regular_path = "benchmark" + os.sep + "pdo_sqlsrv" + os.sep + "regular" +pdo_large_path = "benchmark" + os.sep + "pdo_sqlsrv" + os.sep + "large" + +""" + Path to the connect.php file that contains test database credentials. Note that, the benchmarks are ran against this database and it is different from Result database. +""" connect_file = "lib" + os.sep + "connect.php" connect_file_bak = connect_file + ".bak" + +""" + Global data format used across the script +""" fmt = "%Y-%m-%d %H:%M:%S.0000000" - + def validate_platform( platform_name ): + """ + This module validates the platform name passed in to the script as an argument. + If no match, the script will stop the execution. + Args: + platform_name (str): Platform name to validate + Returns: + N/A + """ platforms = [ "Windows10" , "WidnowsServer2016" @@ -38,6 +66,14 @@ def validate_platform( platform_name ): exit( 1 ) class DB( object ): + """ + A class to keep database credentials + Attributes: + server_name (str): The name or the IP address of the server. + database_name (str): The name of the database + username (str): Database username + password (str): Database password for username + """ def __init__ ( self , server_name = None , database_name = None @@ -49,6 +85,16 @@ class DB( object ): self.password = password class XMLResult( object ): + """ + A class to keep a result set of a benchmark generated by PHPBench as an XML file. + Attributes: + benchmark_name (str): The name or the benchmark. + success (int): 0 or 1. 0 if the benchmark to execute, 1 if the execution was successful. + duration (int,optional): In case of success, time taken to run the benchmark. + memory (int, optional): In case of success, memory peak when executing the benchmark. + iterations(int, optional): In case of success, number of iterations the benchmark was ran for. + error_message(str, optional): In case of failure, descriptive error message. + """ def __init__ ( self , benchmark_name = None , success = None From 007981ef902c26a548cdb7355f3d624558f1b627 Mon Sep 17 00:00:00 2001 From: ulvii Date: Tue, 4 Jul 2017 17:33:02 -0700 Subject: [PATCH 31/48] Updating RedHat setup instructions --- test/Performance/setup_env_unix.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Performance/setup_env_unix.sh b/test/Performance/setup_env_unix.sh index 3b8f9f2a..1150ab88 100644 --- a/test/Performance/setup_env_unix.sh +++ b/test/Performance/setup_env_unix.sh @@ -42,13 +42,13 @@ if [ $PLATFORM = "Ubuntu16" ]; then echo "OK" elif [ $PLATFORM = "RedHat7" ]; then echo "Enabling EPEL repo" - yes | sudo yum install epel-release >> env_setup.log 2>&1 + yes | sudo yum install epel-release -y >> env_setup.log 2>&1 echo "OK" echo "Installing python34-setuptools..." - yes | sudo yum install python34-setuptools >> env_setup.log 2>&1 + yes | sudo yum install python34-setuptools -y >> env_setup.log 2>&1 echo "OK" echo "Installing gcc, git, libxml, openssl, EPEL, python3, pip3..." - yes | sudo yum install -y gcc-c++ libxml2-devel git openssl-devel python34 >> env_setup.log 2>&1 + yes | sudo yum install -y gcc-c++ libxml2-devel git openssl-devel python34 python34-devel >> env_setup.log 2>&1 echo "OK" echo "Installing pip3" yes | sudo easy_install-3.4 pip >> env_setup.log 2>&1 From 0bc68ae4d203ab69dfcbc644bac09afae619e6e5 Mon Sep 17 00:00:00 2001 From: ulvii Date: Wed, 5 Jul 2017 17:23:23 -0700 Subject: [PATCH 32/48] Finished documenting run-perf_tests.py --- test/Performance/run-perf_tests.py | 329 +++++++++++++++++++++++++++-- 1 file changed, 314 insertions(+), 15 deletions(-) diff --git a/test/Performance/run-perf_tests.py b/test/Performance/run-perf_tests.py index 95a8482a..c0891d67 100644 --- a/test/Performance/run-perf_tests.py +++ b/test/Performance/run-perf_tests.py @@ -34,7 +34,7 @@ pdo_regular_path = "benchmark" + os.sep + "pdo_sqlsrv" + os.sep + "regular" pdo_large_path = "benchmark" + os.sep + "pdo_sqlsrv" + os.sep + "large" """ - Path to the connect.php file that contains test database credentials. Note that, the benchmarks are ran against this database and it is different from Result database. + Path to the connect.php file that contains test database credentials. Note that, the benchmarks are run against this database and it is different from Result database. """ connect_file = "lib" + os.sep + "connect.php" connect_file_bak = connect_file + ".bak" @@ -92,7 +92,7 @@ class XMLResult( object ): success (int): 0 or 1. 0 if the benchmark to execute, 1 if the execution was successful. duration (int,optional): In case of success, time taken to run the benchmark. memory (int, optional): In case of success, memory peak when executing the benchmark. - iterations(int, optional): In case of success, number of iterations the benchmark was ran for. + iterations(int, optional): In case of success, number of iterations the benchmark was run for. error_message(str, optional): In case of failure, descriptive error message. """ def __init__ ( self @@ -110,6 +110,15 @@ class XMLResult( object ): self.error_message = error_message def get_test_name( name ): + """ + This module maps PHPBench benchmark names to the names that are used accross the teams. + Args: + name (str): Name of the benchmark + Returns: + The mapped name + Raises: + KeyError when the name passed in does not match any of the keys + """ test_name_dict = { 'SqlsrvConnectionBench': 'connection' , 'SqlsrvCreateDbTableProcBench': 'create' @@ -131,10 +140,30 @@ def get_test_name( name ): return test_name_dict[ name ] def get_run_command( path_to_tests, iterations, dump_file ): - command = "vendor/bin/phpbench run {0} --iterations {1} --dump-file={2}" + """ + This module returns the command to run the tests + Args: + path_to_tests (str): The folder that contains the tests to be run + iterations (str): Number of iterations + dump_file (str): The name of the XML file to output the results + Returns: + The command to run the tests + """ + command = "vendor" + os.sep + "bin" + os.sep + "phpbench run {0} --iterations {1} --dump-file={2}" return command.format( path_to_tests, iterations, dump_file ) def get_id( conn, id_field, table, name_field, value ): + """ + This module returns id of an entry when value is a string + Args: + conn (obj): A connection to the result database + id_field (str): The name of the id column + table (str): The name of the table that contains the entry + name_field (str): The name of the field to compare the value against + value (str): The value that its id is requested + Returns: + id of the value if the value exists in the table, None otherwise + """ query = "SELECT {0} FROM {1} WHERE {2}='{3}'" cursor = conn.cursor() cursor.execute( query.format( id_field, table, name_field, value )) @@ -145,6 +174,19 @@ def get_id( conn, id_field, table, name_field, value ): return id def get_id_no_quote( conn, id_field, table, name_field, value ): + """ + This module returns id of an entry when value is not a string. + @TODO This is a hack, could not get binary binding working with pyodbc. + This module should be removed and get_id should use binding parameters. + Args: + conn (obj): A connection to the result database + id_field (str): The name of the id column + table (str): The name of the table that contains the entry + name_field (str): The name of the field to compare the value against + value (bin): The value that its id is requested + Returns: + id of the value if the value exists in the table, None otherwise + """ query = "SELECT {0} FROM {1} WHERE {2}={3}" cursor = conn.cursor() cursor.execute( query.format( id_field, table, name_field, value )) @@ -155,6 +197,11 @@ def get_id_no_quote( conn, id_field, table, name_field, value ): return id def get_test_database(): + """ + This module reads test database details from connect.php and stores them into an instance of DB class + Returns: + A DB object that contains database credentials + """ test_db = DB() for line in open( connect_file ): if "server" in line: @@ -168,6 +215,13 @@ def get_test_database(): return test_db def connect( db ): + """ + This module creates a connection to the given database + Args: + db (obj): database object + Returns: + A connection object to the given database + """ return pyodbc.connect( driver="{ODBC Driver 13 for SQL Server}" , host=db.server_name @@ -176,7 +230,14 @@ def connect( db ): , password=db.password , autocommit = True) -def get_server_version( server): +def get_server_version( server ): + """ + This module returns the version of the given server + Args: + server (obj): Server object to connect to + Returns: + The output of @@Version + """ conn = connect( server ) cursor = conn.cursor() cursor.execute( "SELECT @@VERSION") @@ -185,6 +246,13 @@ def get_server_version( server): return version def get_sha1_file( filename ): + """ + This module generates sha1sum for the given file + Args: + filename (str): Full path to the file + Returns: + sha1sum hash of the file + """ hash_size = 256 sha1 = hashlib.sha1() with open( filename, 'rb' ) as f: @@ -196,24 +264,57 @@ def get_sha1_file( filename ): return "0x" + sha1.hexdigest() def insert_server_entry( conn, server_name, server_version ): + """ + This module inserts a new entry into Servers table + Args: + conn (obj): Connection object to the Results database + server_name (str): Name of the Test Server that the tests are run against + server_version (str): @@Version of the Test Server + Returns: + N/A + """ query = "INSERT INTO Servers ( HostName, Version ) VALUES ( '{0}', '{1}' )" cursor = conn.cursor() cursor.execute( query.format( server_name, server_version )) cursor.close() def insert_client_entry ( conn, name ): + """ + This module inserts a new entry into Clients table + Args: + conn (obj): Connection object to the Results database + name (str): Name of the Client machine that the tests are run on + Returns: + N/A + """ query = "INSERT INTO Clients ( HostName ) VALUES( '{0}' )" cursor = conn.cursor() cursor.execute( query.format( name )) cursor.close() def insert_team_entry ( conn, name ): + """ + This module inserts a new entry into Teams table + Args: + conn (obj): Connection object to the Results database + name (str): Team name + Returns: + N/A + """ query = "INSERT INTO Teams ( TeamName ) VALUES( '{0}' )" cursor = conn.cursor() cursor.execute( query.format( name )) cursor.close() def insert_test_entry( conn, name ): + """ + This module inserts a new entry into PerformanceTests table + Args: + conn (obj): Connection object to the Results database + name (str): Test name + Returns: + N/A + """ #TO-DO Remove unnecessary columns from the table and fix the query string. Amd64 and 0 are used to bypass not null query = "INSERT INTO PerformanceTests ( TestName, Arch, HashVer ) VALUES( '{0}', 'Amd64', 0 )" cursor = conn.cursor() @@ -221,6 +322,15 @@ def insert_test_entry( conn, name ): cursor.close() def insert_driver_entry( conn, driver_path, driver_hash ): + """ + This module inserts a new entry into Drivers table + Args: + conn (obj): Connection object to the Results database + name (str): Full path to the driver + driver_hash (bin): sha1sum hash of the driver + Returns: + N/A + """ file_date = time.strftime( fmt, time.gmtime( os.path.getmtime( driver_path ))) query = "INSERT INTO Drivers ( Arch, FileDate, SHA1, HashVer ) VALUES ( ?, ?, {0}, 1 )" cursor = conn.cursor() @@ -228,6 +338,15 @@ def insert_driver_entry( conn, driver_path, driver_hash ): cursor.close() def get_server_id( conn, test_db ): + """ + This module retrieves the id of a Server entry. If the given server does not exist in Servers table, + the module inserts it into the Servers table and retrieves its id. + Args: + conn (obj): Connection object to the Results database + test_db (obj): An object that contains Test Server details + Returns: + id of the given server + """ server_id = get_id( conn, "ServerId", "Servers", "HostName", test_db.server_name ) if server_id is None: insert_server_entry( conn, test_db.server_name, get_server_version( test_db )) @@ -235,6 +354,14 @@ def get_server_id( conn, test_db ): return server_id def get_client_id( conn ): + """ + This module retrieves the id of a Client entry. If the given client does not exist in Clients table, + the module inserts it into the Clients table and retrieves its id. + Args: + conn (obj): Connection object to the Results database + Returns: + id of the client + """ client_name = platform.node() client_id = get_id( conn, "ClientId", "Clients", "HostName", client_name ) if client_id is None: @@ -243,6 +370,14 @@ def get_client_id( conn ): return client_id def get_team_id( conn ): + """ + This module retrieves the id of a Team entry. If the given team name - PHP does not exist in Teams table, + the module inserts it into the Teams table and retrieves its id. + Args: + conn (obj): Connection object to the Results database + Returns: + id of the team + """ team_name = "PHP" team_id = get_id( conn, "TeamId", "Teams", "TeamName", team_name) if team_id is None: @@ -251,6 +386,15 @@ def get_team_id( conn ): return team_id def get_test_id( conn, test_name ): + """ + This module retrieves the id of a Test entry. If the given test does not exists in PerformanceTests table, + the module inserts it into the PerformanceTests table and retrieves its id. + Args: + conn (obj): Connection object to the Results database + test_name (str): The name of the test that the id is requested for + Returns: + id of the test + """ test_id = get_id( conn, "TestId", "PerformanceTests", "TestName", test_name ) if test_id is None: insert_test_entry( conn, test_name ) @@ -258,6 +402,15 @@ def get_test_id( conn, test_name ): return test_id def get_driver_id( conn, driver_name ): + """ + This module retrieves the id of a Driver entry. If the given driver does not exists in Drivers table, + the module inserts it into the Drivers table and retrieves its id. + Args: + conn (obj): Connection object to the Results database + driver_name (str): The name of the driver that the id is requested for + Returns: + id of the driver + """ driver_path = get_path_to_driver( driver_name ) driver_hash = get_sha1_file( driver_path ) driver_id = get_id_no_quote( conn, "DriverId", "Drivers", "SHA1", driver_hash ) @@ -267,6 +420,19 @@ def get_driver_id( conn, driver_name ): return driver_id def insert_result_entry_and_get_id( conn, test_id, client_id, driver_id, server_id, team_id, success ): + """ + This module inserts a new result entry into PerformanceResults table and retrieves its id. + Args: + conn (obj): Connection object to the Results database + test_id (int): The id of the test + client_id (int): The id of the client that the test was run on + driver_id (int): The id of the driver that the test was run against + server_id (int): The id of the server that the test was run against + team_id (int): The id of the team that the test belongs to + success (int): 0 if the test failed, 1 otherwise + Returns: + id of the result + """ query = "INSERT INTO PerformanceResults( TestId, ClientId, DriverId, ServerId, TeamId, Success ) OUTPUT INSERTED.ResultId VALUES( {0}, {1}, {2}, {3}, {4}, {5} )" cursor = conn.cursor() cursor.execute( query.format( test_id, client_id, driver_id, server_id, team_id, success )) @@ -277,12 +443,30 @@ def insert_result_entry_and_get_id( conn, test_id, client_id, driver_id, server_ return id def insert_key_value( conn, table_name, result_id, key, value ): + """ + This module inserts a new entry into a key-value table. + Args: + conn (obj): Connection object to the Results database + table_name (string): The name of the table. Current possible values: KeyValueTableBigInt, KeyValueTableDate, KeyValueTableString + result_id (int): The result id that is associated with the key-value table + key (str): name of the property + value (int, date, string): The value of the key + Returns: + N/A + """ query = "INSERT INTO {0} ( ResultId, name, value ) VALUES( ?, ?, ? )" cursor = conn.cursor() cursor.execute( query.format( table_name ), ( result_id, key, value ) ) cursor.close() def get_php_arch(): + """ + This module determines the architecture of the default php of the system + Args: + N/A + Returns + x86 or x64 + """ p = subprocess.Popen( "php -r 'echo PHP_INT_SIZE;'", stdout=subprocess.PIPE, shell = True ) out, err = p.communicate() if out.decode('ascii') == "8": @@ -291,11 +475,25 @@ def get_php_arch(): return "x86" def get_php_version(): + """ + This module determines the version of the default php of the system + Args: + N/A + Returns: + php version + """ p = subprocess.Popen( "php -r 'echo phpversion();'", stdout=subprocess.PIPE, shell = True ) out, err = p.communicate() return out.decode('ascii') def get_php_thread(): + """ + This module determines the thread safety of the default php of the system + Args: + N/A + Returns: + nts or ts + """ if os.name == 'nt': command = "php -i | findstr 'Thread'" else: @@ -308,6 +506,13 @@ def get_php_thread(): return "ts" def get_driver_version( driver_name ): + """ + This module determines the version of the given php driver. + Args: + driver_name (str): Name of the driver. Possible values sqlsrv and pdo_sqlsrv + Returns: + The version of the given driver + """ command = "php -r \"echo phpversion('{0}');\"" print(command.format( driver_name )) p = subprocess.Popen( command.format( driver_name ), stdout=subprocess.PIPE, shell = True ) @@ -315,12 +520,26 @@ def get_driver_version( driver_name ): return out.decode('ascii') def get_msodbcsql_version( test_db ): + """ + This module determines the version of MSODBCSQL using the sqlsrv driver. + Args: + test_db (obj): An object that contains Test Server details + Returns: + MSODBCSQL version + """ command = "php -r \"echo sqlsrv_client_info( sqlsrv_connect( '{0}', array( 'UID'=>'{1}', 'PWD'=>'{2}')))['DriverName'];\"" p = subprocess.Popen( command.format( test_db.server_name, test_db.username, test_db.password ), stdout=subprocess.PIPE, shell = True ) out, err = p.communicate() return out.decode('ascii') def get_path_to_driver( driver_name ): + """ + This module returns the full path to the given php driver + Args: + driver_name (str): Name of the driver. Possible values sqlsrv and pdo_sqlsrv + Returns: + Full path to the given driver + """ p = subprocess.Popen( "php -r \"echo ini_get('extension_dir');\"", stdout=subprocess.PIPE, shell = True ) out, err = p.communicate() extension_dir = out.decode('ascii') @@ -330,17 +549,30 @@ def get_path_to_driver( driver_name ): return extension_dir + os.sep + driver_name + ".so" def enable_mars(): + """ + This module enables MARS by modifying connect.php file + """ print( "Enabling MARS...") with fileinput.FileInput( connect_file, inplace=True, backup='.bak') as file: for line in file: print( line.replace( "$mars=false;", "$mars=true;" ), end='') def disable_mars(): + """ + This module disables MARS by modifying connect.php file + """ print( "Disabling MARS...") os.remove( connect_file ) copyfile( connect_file_bak, connect_file ) def enable_pooling(): + """ + This module enables Connection Pooling. + On Windows, this is done by modifying connect.php file. + On Linux and Mac, odbcinst.ini file needs to be modified. + @TO-DO: Currently modifying odbcinst.ini requires root permissions. + Copy the MSODBCSQL to a location which does not require sudo. + """ print( "Enabling Pooling...") if os.name == 'nt': with fileinput.FileInput( connect_file, inplace=True, backup='.bak') as file: @@ -361,6 +593,13 @@ def enable_pooling(): f.write( lines_to_append ) def disable_pooling(): + """ + This module disables Connection Pooling. + On Windows, this is done by modifying connect.php file. + On Linux and Mac, odbcinst.ini file needs to be modified. + @TO-DO: Currently modifying odbcinst.ini requires root permissions. + Copy the MSODBCSQL to a location which does not require sudo. + """ print("Disabling Pooling...") if os.name == 'nt': os.remove( connect_file ) @@ -374,6 +613,14 @@ def disable_pooling(): os.remove( odbcinst_bak ) def run_tests( iterations, iterations_large ): + """ + This module runs the tests using PHPBench + Args: + iterations (int): Number of iterations the tests in "regular" folder are run for + iterations_large (int): Number of iterations the tests in "large" folder are run for + Returns: + N/A + """ print("Running the tests...") call( get_run_command( sqlsrv_regular_path, iterations, "sqlsrv-regular.xml" ), shell=True ) call( get_run_command( sqlsrv_large_path, iterations_large, "sqlsrv-large.xml" ), shell=True ) @@ -382,22 +629,39 @@ def run_tests( iterations, iterations_large ): call( get_run_command( pdo_large_path, iterations_large, "pdo_sqlsrv-large.xml" ), shell=True ) def parse_results( dump_file ): + """ + This module parses the .xml files generated by PHPBench + @TO-DO: Currently only limited detailes are parsed, such as duration and peak memory. + PHPBench reports a lot more information that can be helpful. + Consider looking at the xml files. + Args: + dump_file (str): The name of the XML file to be parsed. + Returns: + N/A + """ xml_results = [] tree = ET.parse( dump_file ) root = tree.getroot() + # The following lines assume a certain xml structure. + # Get all the benchmarks in a list benchmarks = root[0].findall( 'benchmark' ) for benchmark in benchmarks: xml_result = XMLResult() + #Get the benchmark name and remove the leasing backslash xml_result.benchmark_name = benchmark.get( 'class' )[1:] errors = benchmark[0][0].find( 'errors' ) + # Store the error message and mark the benchmark as failed if something went wrong when running the benchmark. if( errors is not None ): xml_result.success = 0 xml_result.error_message = errors[0].text + # If the bechmark was run successfully, parse the results. This is where you would add code to parse more details about the benchmark. else: xml_result.success = 1 xml_result.duration = int( round( int( benchmark[0][0].find( 'stats' ).get( 'sum' )) / 1000000 )) iterations = benchmark[0][0].findall( 'iteration' ) xml_result.iterations = len( iterations ) + # Memory peak is an iteration specific, so going through all the iterations and capturing the highest. + # Memory peak is usually the same for all iterations. memory_peak = 0 for iteration in iterations: iter_memory_peak = int( iteration.get( 'mem-peak' )) @@ -408,7 +672,21 @@ def parse_results( dump_file ): return xml_results def parse_and_store_results( dump_file, test_db, result_db, platform, driver, start_time, mars, pooling ): - + """ + This module parses the given xml file and stores the results into Result Database. + Args: + dump_file (str): Name of the xml file that containst the results from PHPBench + test_db (obj): An object that contains Test Database details + result_db (obj): An object that contains Result Database details + platform (str): The platform name that the tests are run on + driver (str): Name of the driver, sqlsrv or pdo_sqlsrv + start_time (date): Time when the script was run + mars (int): 0 to turn MARS off, 1 otherwise + pooling (int): 0 to turn Connection Pooling off, 1 otherwise + Returns: + N/A + """ + # Connect to the Result Database conn = connect( result_db ) server_id = get_server_id( conn, test_db ) @@ -424,8 +702,9 @@ def parse_and_store_results( dump_file, test_db, result_db, platform, driver, st msodbcsql_version = get_msodbcsql_version( test_db ) cursor = conn.cursor() + #parse the results from xml file results = parse_results( dump_file ) - + # Store every result into the Result Database for result in results: test_name = get_test_name( result.benchmark_name ) test_id = get_test_id( conn, test_name ) @@ -449,6 +728,19 @@ def parse_and_store_results( dump_file, test_db, result_db, platform, driver, st insert_key_value( conn, "KeyValueTableString", result_id, "msodbcsql" , msodbcsql_version ) def parse_and_store_results_all( test_db, result_db, platform, start_time, mars, pooling ): + """ + This module parses the given sqlsrv-regular.xml, sqlsrv-large.xml,pdo_sqlsrv-regular.xml, pdo_sqlsrv-large.xml and stores the results into Result Database. + Args: + test_db (obj): An object that contains Test Database details + result_db (obj): An object that contains Result Database details + platform (str): The platform name that the tests are run on + start_time (date): Time when the script was run + mars (int): 0 to turn MARS off, 1 otherwise + pooling (int): 0 to turn Connection Pooling off, 1 otherwise + Returns: + N/A + + """ print("Parsing and storing the results...") parse_and_store_results( "sqlsrv-regular.xml", test_db, result_db, platform, "sqlsrv", start_time, mars, pooling ) parse_and_store_results( "sqlsrv-large.xml", test_db, result_db, platform, "sqlsrv", start_time, mars, pooling ) @@ -457,15 +749,17 @@ def parse_and_store_results_all( test_db, result_db, platform, start_time, mars, if __name__ == '__main__': parser = argparse.ArgumentParser() - parser.add_argument( '-platform', '--PLATFORM', required=True ) - parser.add_argument( '-iterations', '--ITERATIONS', type=int , required=True ) - parser.add_argument( '-iterations-large', '--ITERATIONS_LARGE',type=int , required=True ) - parser.add_argument( '-result-server', '--RESULT_SERVER', required=True ) - parser.add_argument( '-result-db', '--RESULT_DB', required=True ) - parser.add_argument( '-result-uid', '--RESULT_UID', required=True ) - parser.add_argument( '-result-pwd', '--RESULT_PWD', required=True ) + parser.add_argument( '-platform', '--PLATFORM', required=True, help='The name of the platform the tests run on' ) + parser.add_argument( '-iterations', '--ITERATIONS', required=True, help='Number of iterations for regular tests', type=int ) + parser.add_argument( '-iterations-large', '--ITERATIONS_LARGE', required=True, help='Number of iterations for regular tests' type=int ) + parser.add_argument( '-result-server', '--RESULT_SERVER', required=True, help='IP address of the Result Server' ) + parser.add_argument( '-result-db', '--RESULT_DB', required=True, help='Name of the Result Database' ) + parser.add_argument( '-result-uid', '--RESULT_UID', required=True, help='Username to connect to the Result Database' ) + parser.add_argument( '-result-pwd', '--RESULT_PWD', required=True, help='Password to connect to the Result Database' ) args = parser.parse_args() - + + # Start time is recorded only in the beginning of this script execution. So it is not benchmark specific. + # Start time can be used to group the results start_time = datetime.datetime.now().strftime( fmt ) print( "Start time: " + start_time ) @@ -477,7 +771,10 @@ if __name__ == '__main__': run_tests( args.ITERATIONS, args.ITERATIONS_LARGE ) parse_and_store_results_all( test_db, result_db, args.PLATFORM, start_time, 0, 0 ) - + """ + The following lines are commented out, because it already take a long time to run the tests with the default settings. + Echo block can be uncommented and run separately. + print("Running the tests with MARS ON...") enable_mars() run_tests( args.ITERATIONS, args.ITERATIONS_LARGE ) @@ -490,5 +787,7 @@ if __name__ == '__main__': run_tests( args.ITERATIONS, args.ITERATIONS_LARGE ) parse_and_store_results_all( test_db, result_db, args.PLATFORM, start_time, 0, 1 ) disable_pooling() + """ + exit() \ No newline at end of file From 66390984469f4ff6a223b1941f9730b4479d012b Mon Sep 17 00:00:00 2001 From: ulvii Date: Wed, 5 Jul 2017 17:26:14 -0700 Subject: [PATCH 33/48] Finished documenting run-perf_tests.py --- test/Performance/run-perf_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Performance/run-perf_tests.py b/test/Performance/run-perf_tests.py index c0891d67..4840e6e6 100644 --- a/test/Performance/run-perf_tests.py +++ b/test/Performance/run-perf_tests.py @@ -751,7 +751,7 @@ if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument( '-platform', '--PLATFORM', required=True, help='The name of the platform the tests run on' ) parser.add_argument( '-iterations', '--ITERATIONS', required=True, help='Number of iterations for regular tests', type=int ) - parser.add_argument( '-iterations-large', '--ITERATIONS_LARGE', required=True, help='Number of iterations for regular tests' type=int ) + parser.add_argument( '-iterations-large', '--ITERATIONS_LARGE', required=True, help='Number of iterations for regular tests', type=int ) parser.add_argument( '-result-server', '--RESULT_SERVER', required=True, help='IP address of the Result Server' ) parser.add_argument( '-result-db', '--RESULT_DB', required=True, help='Name of the Result Database' ) parser.add_argument( '-result-uid', '--RESULT_UID', required=True, help='Username to connect to the Result Database' ) From af3ea7023b3f547cfb7e420d48a18c1e6163dccc Mon Sep 17 00:00:00 2001 From: ulvii Date: Thu, 6 Jul 2017 17:19:21 -0700 Subject: [PATCH 34/48] Fixing a few issues found while testing the scripts on Windows --- test/Performance/run-perf_tests.py | 11 +++--- test/Performance/setup_env_windows.ps1 | 47 +++++++++++--------------- 2 files changed, 24 insertions(+), 34 deletions(-) diff --git a/test/Performance/run-perf_tests.py b/test/Performance/run-perf_tests.py index 4840e6e6..d7260d43 100644 --- a/test/Performance/run-perf_tests.py +++ b/test/Performance/run-perf_tests.py @@ -467,7 +467,7 @@ def get_php_arch(): Returns x86 or x64 """ - p = subprocess.Popen( "php -r 'echo PHP_INT_SIZE;'", stdout=subprocess.PIPE, shell = True ) + p = subprocess.Popen( "php -r \"echo PHP_INT_SIZE;\"", stdout=subprocess.PIPE, shell = True ) out, err = p.communicate() if out.decode('ascii') == "8": return "x64" @@ -482,7 +482,7 @@ def get_php_version(): Returns: php version """ - p = subprocess.Popen( "php -r 'echo phpversion();'", stdout=subprocess.PIPE, shell = True ) + p = subprocess.Popen( "php -r \"echo phpversion();\"", stdout=subprocess.PIPE, shell = True ) out, err = p.communicate() return out.decode('ascii') @@ -495,7 +495,7 @@ def get_php_thread(): nts or ts """ if os.name == 'nt': - command = "php -i | findstr 'Thread'" + command = "php -i | findstr \"Thread\"" else: command = "php -i | grep 'Thread'" p = subprocess.Popen( command, stdout=subprocess.PIPE, shell = True ) @@ -514,7 +514,6 @@ def get_driver_version( driver_name ): The version of the given driver """ command = "php -r \"echo phpversion('{0}');\"" - print(command.format( driver_name )) p = subprocess.Popen( command.format( driver_name ), stdout=subprocess.PIPE, shell = True ) out, err = p.communicate() return out.decode('ascii') @@ -527,7 +526,7 @@ def get_msodbcsql_version( test_db ): Returns: MSODBCSQL version """ - command = "php -r \"echo sqlsrv_client_info( sqlsrv_connect( '{0}', array( 'UID'=>'{1}', 'PWD'=>'{2}')))['DriverName'];\"" + command = "php -r \"echo sqlsrv_client_info( sqlsrv_connect( '{0}', array( 'UID'=>'{1}', 'PWD'=>'{2}')))['DriverVer'];\"" p = subprocess.Popen( command.format( test_db.server_name, test_db.username, test_db.password ), stdout=subprocess.PIPE, shell = True ) out, err = p.communicate() return out.decode('ascii') @@ -790,4 +789,4 @@ if __name__ == '__main__': """ exit() - \ No newline at end of file + \ No newline at end of file diff --git a/test/Performance/setup_env_windows.ps1 b/test/Performance/setup_env_windows.ps1 index f1efbd21..ecce25bc 100644 --- a/test/Performance/setup_env_windows.ps1 +++ b/test/Performance/setup_env_windows.ps1 @@ -9,18 +9,6 @@ Param( [string]$ARCH ) -function Get-UrlStatusCode([string] $Url) -{ - try - { - (Invoke-WebRequest -Uri $Url -UseBasicParsing -DisableKeepAlive).StatusCode - } - catch [Net.WebException] - { - [int]$_.Exception.Response.StatusCode - } -} - IF($ARCH -ne "x64" -And $ARCH -ne "x86"){ Write-Host "ARCH must either x64 or x86" Break @@ -37,38 +25,39 @@ $tempFolder=Join-Path $startingDir "temp" Remove-Item temp -Recurse -Force -ErrorAction Ignore New-Item -ItemType directory -Path temp -(New-Object System.Net.WebClient).DownloadFile('http://windows.php.net/downloads/releases/sha1sum.txt',"$tempFolder\sha1sum.txt") +(New-Object System.Net.WebClient).DownloadFile("http://windows.php.net/downloads/releases/sha1sum.txt","$tempFolder\sha1sum.txt") $PHP70_LATEST_VERSION=type $tempFolder\sha1sum.txt | where { $_ -match "php-(7.0\.\d+)-src" } | foreach { $matches[1] } $PHP71_LATEST_VERSION=type $tempFolder\sha1sum.txt | where { $_ -match "php-(7.1\.\d+)-src" } | foreach { $matches[1] } -#check if PHP_VERSION source exisits -$statusCode = Get-UrlStatusCode "http://windows.php.net/downloads/releases/php-$PHP_VERSION-src.zip" -#If provided php version source does not exists, default the version to latest php 71 source -IF($statusCode -eq 404){$PHP_VERSION=$PHP71_LATEST_VERSION} + $PHP_VERSION_MINOR=$PHP_VERSION.split(".")[1] Write-Host "Installing chocolatey..." iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) Write-Host "Installing Git..." -choco install git -Write-Host "Downloading Python3..." -(New-Object System.Net.WebClient).DownloadFile('https://www.python.org/ftp/python/3.6.0/python-3.6.0-amd64.exe', "$tempFolder\python.exe") +choco install -y git Write-Host "Installing Python3..." -.\temp\python.exe /quiet InstallAllUsers=1 PrependPath=1 Include_test=0 | Out-Null +choco install -y python3 +RefreshEnv Write-Host "Installing pyodbc..." pip3 install pyodbc | Out-Null Write-Host "Downloading MSODBCSQL..." +#This needs to be manually updated when there is a new release (New-object System.Net.WebClient).DownloadFile('https://download.microsoft.com/download/D/5/E/D5EEF288-A277-45C8-855B-8E2CB7E25B96/x64/msodbcsql.msi', "$tempFolder\msodbcsql.msi") Write-Host "Installing MSODBCSQL..." msiexec /quiet /passive /qn /i $tempFolder\msodbcsql.msi IACCEPTMSODBCSQLLICENSETERMS=YES | Out-Null -Write-Host "Downloading 7-Zip..." -(New-object System.Net.WebClient).DownloadFile("http://www.7-zip.org/a/7z1604-x64.exe", "$tempFolder\7z1604-x64.exe") Write-Host "Installing 7-Zip..." -.\temp\7z1604-x64.exe /S | Out-Null -set-alias sz "$env:ProgramFiles\7-Zip\7z.exe" +choco install -y 7zip.install + Write-Host "Downloading PHP-SDK..." (New-Object System.Net.WebClient).DownloadFile('http://windows.php.net/downloads/php-sdk/php-sdk-binary-tools-20110915.zip', "$tempFolder\binary_tools.zip") Write-Host "Downloading PHP-$PHP_VERSION source..." +IF($PHP_VERSION -eq $PHP70_LATEST_VERSION -Or $PHP_VERSION -eq $PHP71_LATEST_VERSION){ (New-Object System.Net.WebClient).DownloadFile("http://windows.php.net/downloads/releases/php-$PHP_VERSION-src.zip", "$tempFolder\php-$PHP_VERSION-src.zip") +} +ELSE{ +(New-Object System.Net.WebClient).DownloadFile("http://windows.php.net/downloads/releases/archives/php-$PHP_VERSION-src.zip", "$tempFolder\php-$PHP_VERSION-src.zip") +} + Write-Host "Downloading Dependencies..." (New-Object System.Net.WebClient).DownloadFile("http://windows.php.net/downloads/php-sdk/deps-7.$PHP_VERSION_MINOR-vc14-$ARCH.7z", "$tempFolder\deps-7.$PHP_VERSION_MINOR-vc14-$ARCH.7z") @@ -81,8 +70,7 @@ bin\phpsdk_buildtree.bat phpdev New-Item -ItemType directory -Path .\phpdev\vc14 Copy-Item .\phpdev\vc9\* phpdev\vc14\ -recurse [System.IO.Compression.ZipFile]::ExtractToDirectory("$tempFolder\php-$PHP_VERSION-src.zip", "C:\php-sdk\phpdev\vc14\$ARCH\") -set-alias sz "$env:ProgramFiles\7-Zip\7z.exe" -sz x $tempFolder\deps-7.$PHP_VERSION_MINOR-vc14-$ARCH.7z -oC:\php-sdk\phpdev\vc14\$ARCH\ +7z.exe x $tempFolder\deps-7.$PHP_VERSION_MINOR-vc14-$ARCH.7z -oC:\php-sdk\phpdev\vc14\$ARCH\ bin\phpsdk_setvars.bat @@ -103,6 +91,8 @@ if ($PHP_THREAD -ceq "nts") { & $startingDir\compile_php.bat $ARCH $CONFIG_OPTIONS + + Copy-Item php.ini-production php.ini Add-Content php.ini "extension=C:\php\ext\php_sqlsrv.dll" Add-Content php.ini "extension=C:\php\ext\php_pdo_sqlsrv.dll" @@ -112,7 +102,8 @@ Copy-Item C:\php-sdk\phpdev\vc14\$ARCH\deps\bin\ssleay32.dll C:\Windows -force Copy-Item C:\php-sdk\phpdev\vc14\$ARCH\deps\bin\libeay32.dll C:\Windows -force cd $startingDir -set-alias php "C:\php\php.exe" +$env:Path += ";C:\php\" +RefreshEnv wget https://getcomposer.org/installer -O composer-setup.php php composer-setup.php php composer.phar install \ No newline at end of file From bfaf87bfb5d0fca84ac8466de8958f665801783b Mon Sep 17 00:00:00 2001 From: ulvii Date: Thu, 6 Jul 2017 18:00:33 -0700 Subject: [PATCH 35/48] Fixing an issue with pip3 --- test/Performance/setup_env_windows.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Performance/setup_env_windows.ps1 b/test/Performance/setup_env_windows.ps1 index ecce25bc..4868a0b4 100644 --- a/test/Performance/setup_env_windows.ps1 +++ b/test/Performance/setup_env_windows.ps1 @@ -39,7 +39,7 @@ Write-Host "Installing Python3..." choco install -y python3 RefreshEnv Write-Host "Installing pyodbc..." -pip3 install pyodbc | Out-Null +C:\Python*\Scripts\pip3.exe install pyodbc | Out-Null Write-Host "Downloading MSODBCSQL..." #This needs to be manually updated when there is a new release (New-object System.Net.WebClient).DownloadFile('https://download.microsoft.com/download/D/5/E/D5EEF288-A277-45C8-855B-8E2CB7E25B96/x64/msodbcsql.msi', "$tempFolder\msodbcsql.msi") From 6466606cbc9bb7c82fb739087f796561002fc657 Mon Sep 17 00:00:00 2001 From: ulvii Date: Thu, 6 Jul 2017 18:43:31 -0700 Subject: [PATCH 36/48] A few minor fixes --- test/Performance/README.md | 7 +++---- test/Performance/run-perf_tests.py | 4 ++-- test/Performance/setup_env_windows.ps1 | 5 ++++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/test/Performance/README.md b/test/Performance/README.md index 151d2eb2..42458544 100644 --- a/test/Performance/README.md +++ b/test/Performance/README.md @@ -6,8 +6,7 @@ Run `cmd` as administrator. powershell Set-ExecutionPolicy Unrestricted - .\setup_env_windows.ps1 -If `PHP_VERSION` is wrong, the script will default it to the latest PHP 7.1 version + .\setup_env_windows.ps1 ### Ubuntu 16 sudo env “PATH=$PATH” bash setup_env_unix.sh Ubuntu16 @@ -21,9 +20,9 @@ If `PHP_VERSION` is wrong, the script will default it to the latest PHP 7.1 vers ### 1. Modify lib/connect.php with the test database credetials ### 2. Execute run-perf_tests.py. -The script must be executed with `sudo` because to enable pooling it needs to modify odbcinst.ini system file. As an improvement, the location of the odbcinst.ini file can be changed so that, sudo is not requiered. +The script must be executed with `sudo python3` because to enable pooling it needs to modify odbcinst.ini system file. As an improvement, the location of the odbcinst.ini file can be changed so that, sudo is not requiered. - run-perf_tests.py -platform -iterations -iterations-large -result-server -result-db -result-uid -result-pwd + py.exe run-perf_tests.py -platform -iterations -iterations-large -result-server -result-db -result-uid -result-pwd `-platform` - The platform that the tests are ran on. Must be one of the following: Windows10, WidnowsServer2016 WindowsServer2012 Ubuntu16 RedHat7 Sierra `-iterations` - The number of iterations for regular tests. diff --git a/test/Performance/run-perf_tests.py b/test/Performance/run-perf_tests.py index d7260d43..85ccc579 100644 --- a/test/Performance/run-perf_tests.py +++ b/test/Performance/run-perf_tests.py @@ -55,7 +55,7 @@ def validate_platform( platform_name ): """ platforms = [ "Windows10" - , "WidnowsServer2016" + , "WindowsServer2016" , "WindowsServer2012" , "Ubuntu16" , "RedHat7" @@ -526,7 +526,7 @@ def get_msodbcsql_version( test_db ): Returns: MSODBCSQL version """ - command = "php -r \"echo sqlsrv_client_info( sqlsrv_connect( '{0}', array( 'UID'=>'{1}', 'PWD'=>'{2}')))['DriverVer'];\"" + command = "php -r \"echo sqlsrv_client_info( sqlsrv_connect( '{0}', array( 'UID'=>'{1}', 'PWD'=>'{2}')))['DriverVer'];\"" p = subprocess.Popen( command.format( test_db.server_name, test_db.username, test_db.password ), stdout=subprocess.PIPE, shell = True ) out, err = p.communicate() return out.decode('ascii') diff --git a/test/Performance/setup_env_windows.ps1 b/test/Performance/setup_env_windows.ps1 index 4868a0b4..dc1aff65 100644 --- a/test/Performance/setup_env_windows.ps1 +++ b/test/Performance/setup_env_windows.ps1 @@ -35,6 +35,7 @@ Write-Host "Installing chocolatey..." iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) Write-Host "Installing Git..." choco install -y git +Set-Alias git 'C:\Program Files\Git\cmd\git.exe' Write-Host "Installing Python3..." choco install -y python3 RefreshEnv @@ -106,4 +107,6 @@ $env:Path += ";C:\php\" RefreshEnv wget https://getcomposer.org/installer -O composer-setup.php php composer-setup.php -php composer.phar install \ No newline at end of file +php composer.phar install +Remove-Item temp -Recurse -Force -ErrorAction Ignore +Write-Host "Setup completed!" \ No newline at end of file From 4aee258fe44e5c76f8a043d7fa97ae5d6d28cdca Mon Sep 17 00:00:00 2001 From: ulvii Date: Fri, 7 Jul 2017 18:04:04 -0700 Subject: [PATCH 37/48] Fixing minor issues in unix setup scripts --- test/Performance/setup_env_unix.sh | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/test/Performance/setup_env_unix.sh b/test/Performance/setup_env_unix.sh index 1150ab88..f5f9c00b 100644 --- a/test/Performance/setup_env_unix.sh +++ b/test/Performance/setup_env_unix.sh @@ -27,8 +27,11 @@ fi rm -rf env_setup.log touch env_setup.log if [ $PLATFORM = "Ubuntu16" ]; then - echo "Installing git, curl, libxml, autoconf, openssl, python3, pip3..." - yes | sudo apt-get install git curl autoconf libxml2-dev libssl-dev pkg-config python3 python3-pip >> env_setup.log 2>&1 + echo "Update..." + yes | sudo dpkg --configure -a >> env_setup.log 2>&1 + yes | sudo apt-get update >> env_setup.log 2>&1 + echo "Installing git, zip, curl, libxml, autoconf, openssl, python3, pip3..." + yes | sudo apt-get install git zip curl autoconf libxml2-dev libssl-dev pkg-config python3 python3-pip >> env_setup.log 2>&1 echo "OK" echo "Installing MSODBCSQL..." curl -s https://packages.microsoft.com/keys/microsoft.asc | apt-key add - @@ -41,14 +44,16 @@ if [ $PLATFORM = "Ubuntu16" ]; then pip3 install pyodbc >> env_setup.log 2>&1 echo "OK" elif [ $PLATFORM = "RedHat7" ]; then - echo "Enabling EPEL repo" + echo "Update..." + yes | sudo yum update >> env_setup.log 2>&1 + echo "Enabling EPEL repo..." yes | sudo yum install epel-release -y >> env_setup.log 2>&1 echo "OK" echo "Installing python34-setuptools..." yes | sudo yum install python34-setuptools -y >> env_setup.log 2>&1 echo "OK" - echo "Installing gcc, git, libxml, openssl, EPEL, python3, pip3..." - yes | sudo yum install -y gcc-c++ libxml2-devel git openssl-devel python34 python34-devel >> env_setup.log 2>&1 + echo "Installing gcc, git, zip libxml, openssl, EPEL, python3, pip3..." + yes | sudo yum install -y gcc-c++ libxml2-devel git zip openssl-devel python34 python34-devel >> env_setup.log 2>&1 echo "OK" echo "Installing pip3" yes | sudo easy_install-3.4 pip >> env_setup.log 2>&1 From 78a8c67305adfdd9166522765074bfcfee2c21da Mon Sep 17 00:00:00 2001 From: ulvii Date: Wed, 12 Jul 2017 13:35:15 -0700 Subject: [PATCH 38/48] Applying changes based on the review comments --- .../regular/PDOCreateDbTableProcBench.php | 2 +- test/Performance/report.sql | 2 +- test/Performance/run-perf_tests.py | 33 ++++++++++--------- test/Performance/setup_env_windows.ps1 | 2 +- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/test/Performance/benchmark/pdo_sqlsrv/regular/PDOCreateDbTableProcBench.php b/test/Performance/benchmark/pdo_sqlsrv/regular/PDOCreateDbTableProcBench.php index 53642b6a..ef27cf39 100644 --- a/test/Performance/benchmark/pdo_sqlsrv/regular/PDOCreateDbTableProcBench.php +++ b/test/Performance/benchmark/pdo_sqlsrv/regular/PDOCreateDbTableProcBench.php @@ -13,7 +13,7 @@ class PDOCreateDbTableProcBench{ } /* * Each iteration creates a database, a table and a stored procedure in that database and drops the database at the end. - * Not that, execDirect function are used to execute all the queries. + * Note that, execDirect function are used to execute all the queries. */ public function benchCreateDbTableProc(){ $randomNum = rand(); diff --git a/test/Performance/report.sql b/test/Performance/report.sql index 981aa1cc..859e769a 100644 --- a/test/Performance/report.sql +++ b/test/Performance/report.sql @@ -1,4 +1,4 @@ ---The script can be run to read the results +--The script can be run to read the results. You can filter out the results ran on a certain date by changing the date at the end. select t1.ResultId, Test, Client, Server, Driver, Duration, Memory, Success, Team, StartTime from ( select pr.ResultId, pr.Success, pt.TestName as Test, cl.HostName as Client, srv.HostName as Server, diff --git a/test/Performance/run-perf_tests.py b/test/Performance/run-perf_tests.py index 85ccc579..d68fd154 100644 --- a/test/Performance/run-perf_tests.py +++ b/test/Performance/run-perf_tests.py @@ -89,7 +89,7 @@ class XMLResult( object ): A class to keep a result set of a benchmark generated by PHPBench as an XML file. Attributes: benchmark_name (str): The name or the benchmark. - success (int): 0 or 1. 0 if the benchmark to execute, 1 if the execution was successful. + success (int): 0 or 1. 0 if the benchmark failed to execute, 1 if the execution was successful. duration (int,optional): In case of success, time taken to run the benchmark. memory (int, optional): In case of success, memory peak when executing the benchmark. iterations(int, optional): In case of success, number of iterations the benchmark was run for. @@ -442,7 +442,7 @@ def insert_result_entry_and_get_id( conn, test_id, client_id, driver_id, server_ return result_id[0] return id -def insert_key_value( conn, table_name, result_id, key, value ): +def insert_result_key_value( conn, table_name, result_id, key, value ): """ This module inserts a new entry into a key-value table. Args: @@ -636,7 +636,7 @@ def parse_results( dump_file ): Args: dump_file (str): The name of the XML file to be parsed. Returns: - N/A + An array of XMLResult objects, where each object contains benchmark information, such as duration and memory. """ xml_results = [] tree = ET.parse( dump_file ) @@ -710,21 +710,22 @@ def parse_and_store_results( dump_file, test_db, result_db, platform, driver, st result_id = insert_result_entry_and_get_id( conn, test_id, client_id, driver_id, server_id, team_id, result.success ) if result.success: - insert_key_value( conn, "KeyValueTableBigInt", result_id, "duration", result.duration ) - insert_key_value( conn, "KeyValueTableBigInt", result_id, "memory", result.memory ) - insert_key_value( conn, "KeyValueTableBigInt", result_id, "iterations", result.iterations) + insert_result_key_value( conn, "KeyValueTableBigInt", result_id, "duration", result.duration ) + insert_result_key_value( conn, "KeyValueTableBigInt", result_id, "memory", result.memory ) + insert_result_key_value( conn, "KeyValueTableBigInt", result_id, "iterations", result.iterations) else: - insert_key_value( conn, "KeyValueTableString", result_id, "error", result.error_message ) + insert_result_key_value( conn, "KeyValueTableString", result_id, "error", result.error_message ) - insert_key_value( conn, "KeyValueTableDate" , result_id, "startTime" , start_time ) - insert_key_value( conn, "KeyValueTableBigInt", result_id, "mars" , mars ) - insert_key_value( conn, "KeyValueTableBigInt", result_id, "pooling" , pooling ) - insert_key_value( conn, "KeyValueTableString", result_id, "driver" , driver ) - insert_key_value( conn, "KeyValueTableString", result_id, "php_arch" , php_arch ) - insert_key_value( conn, "KeyValueTableString", result_id, "os" , platform ) - insert_key_value( conn, "KeyValueTableString", result_id, "php_thread" , php_thread ) - insert_key_value( conn, "KeyValueTableString", result_id, "php_version", php_version ) - insert_key_value( conn, "KeyValueTableString", result_id, "msodbcsql" , msodbcsql_version ) + insert_result_key_value( conn, "KeyValueTableDate" , result_id, "startTime" , start_time ) + insert_result_key_value( conn, "KeyValueTableBigInt", result_id, "mars" , mars ) + insert_result_key_value( conn, "KeyValueTableBigInt", result_id, "pooling" , pooling ) + insert_result_key_value( conn, "KeyValueTableString", result_id, "driver" , driver ) + insert_result_key_value( conn, "KeyValueTableString", result_id, "php_arch" , php_arch ) + insert_result_key_value( conn, "KeyValueTableString", result_id, "os" , platform ) + insert_result_key_value( conn, "KeyValueTableString", result_id, "php_thread" , php_thread ) + insert_result_key_value( conn, "KeyValueTableString", result_id, "php_version" , php_version ) + insert_result_key_value( conn, "KeyValueTableString", result_id, "msodbcsql" , msodbcsql_version ) + insert_result_key_value( conn, "KeyValueTableString", result_id, "driver_version" , driver_version ) def parse_and_store_results_all( test_db, result_db, platform, start_time, mars, pooling ): """ diff --git a/test/Performance/setup_env_windows.ps1 b/test/Performance/setup_env_windows.ps1 index dc1aff65..2ac0d766 100644 --- a/test/Performance/setup_env_windows.ps1 +++ b/test/Performance/setup_env_windows.ps1 @@ -103,7 +103,7 @@ Copy-Item C:\php-sdk\phpdev\vc14\$ARCH\deps\bin\ssleay32.dll C:\Windows -force Copy-Item C:\php-sdk\phpdev\vc14\$ARCH\deps\bin\libeay32.dll C:\Windows -force cd $startingDir -$env:Path += ";C:\php\" +[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\php\", [System.EnvironmentVariableTarget]::Machine) RefreshEnv wget https://getcomposer.org/installer -O composer-setup.php php composer-setup.php From 6b2e43e5c78cb51b0e8344a680c4e5721282ed95 Mon Sep 17 00:00:00 2001 From: ulvii Date: Wed, 12 Jul 2017 14:35:54 -0700 Subject: [PATCH 39/48] Update README and a type fix in run-perf_tests.py --- test/Performance/README.md | 3 ++- test/Performance/run-perf_tests.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/test/Performance/README.md b/test/Performance/README.md index 42458544..2108db71 100644 --- a/test/Performance/README.md +++ b/test/Performance/README.md @@ -17,10 +17,11 @@ Run `cmd` as administrator. bash setup_env_unix.sh Sierra ## Run benchmarks +PHPBench is used to run the benchmarks. Visit http://phpbench.readthedocs.io/en/latest/introduction.html to have an idea how the tool works. ### 1. Modify lib/connect.php with the test database credetials ### 2. Execute run-perf_tests.py. -The script must be executed with `sudo python3` because to enable pooling it needs to modify odbcinst.ini system file. As an improvement, the location of the odbcinst.ini file can be changed so that, sudo is not requiered. +On Linux and Mac, the script must be executed with `sudo python3` because to enable pooling it needs to modify odbcinst.ini system file. As an improvement, the location of the odbcinst.ini file can be changed so that, sudo is not requiered. py.exe run-perf_tests.py -platform -iterations -iterations-large -result-server -result-db -result-uid -result-pwd diff --git a/test/Performance/run-perf_tests.py b/test/Performance/run-perf_tests.py index d68fd154..0821011e 100644 --- a/test/Performance/run-perf_tests.py +++ b/test/Performance/run-perf_tests.py @@ -772,7 +772,7 @@ if __name__ == '__main__': run_tests( args.ITERATIONS, args.ITERATIONS_LARGE ) parse_and_store_results_all( test_db, result_db, args.PLATFORM, start_time, 0, 0 ) """ - The following lines are commented out, because it already take a long time to run the tests with the default settings. + The following lines are commented out, because it already takes a long time to run the tests with the default settings. Echo block can be uncommented and run separately. print("Running the tests with MARS ON...") From 45c574e0d797fa8d57dd86b22c19a5986a899b45 Mon Sep 17 00:00:00 2001 From: ulvii Date: Wed, 12 Jul 2017 18:05:03 -0700 Subject: [PATCH 40/48] Adding a check for php version --- test/Performance/setup_env_unix.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Performance/setup_env_unix.sh b/test/Performance/setup_env_unix.sh index f5f9c00b..76e50297 100644 --- a/test/Performance/setup_env_unix.sh +++ b/test/Performance/setup_env_unix.sh @@ -6,7 +6,7 @@ else echo "First argument must be one of Ubuntu16, RedHat7, Sierra. Exiting..." exit 1 fi -if [[ "$2" = "" ]]; then +if [[ "$2" != 7.*.* ]]; then echo "Second argument must be PHP version in format of 7.x.x.Exiting..." exit else From f89da18eb055db939bca49312d43c44759110e26 Mon Sep 17 00:00:00 2001 From: ulvii Date: Thu, 13 Jul 2017 19:13:57 -0700 Subject: [PATCH 41/48] Fixing a few minor issues with RedHat instructions. Also applying review comments to windows setup script --- test/Performance/setup_env_unix.sh | 11 +++++------ test/Performance/setup_env_windows.ps1 | 6 ++++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/test/Performance/setup_env_unix.sh b/test/Performance/setup_env_unix.sh index 76e50297..c1ffc10a 100644 --- a/test/Performance/setup_env_unix.sh +++ b/test/Performance/setup_env_unix.sh @@ -46,17 +46,16 @@ if [ $PLATFORM = "Ubuntu16" ]; then elif [ $PLATFORM = "RedHat7" ]; then echo "Update..." yes | sudo yum update >> env_setup.log 2>&1 + echo "OK" echo "Enabling EPEL repo..." - yes | sudo yum install epel-release -y >> env_setup.log 2>&1 + wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm >> env_setup.log 2>&1 + yes | sudo yum install epel-release-latest-7.noarch.rpm >> env_setup.log 2>&1 echo "OK" echo "Installing python34-setuptools..." yes | sudo yum install python34-setuptools -y >> env_setup.log 2>&1 echo "OK" echo "Installing gcc, git, zip libxml, openssl, EPEL, python3, pip3..." - yes | sudo yum install -y gcc-c++ libxml2-devel git zip openssl-devel python34 python34-devel >> env_setup.log 2>&1 - echo "OK" - echo "Installing pip3" - yes | sudo easy_install-3.4 pip >> env_setup.log 2>&1 + yes | sudo yum install -y gcc-c++ libxml2-devel git zip openssl-devel python34 python34-devel python3-pip >> env_setup.log 2>&1 echo "OK" echo "Installing MSODBCSQL..." curl -s https://packages.microsoft.com/config/rhel/7/prod.repo > /etc/yum.repos.d/mssql-release.repo @@ -121,7 +120,7 @@ make >> ../env_setup.log 2>&1 echo "OK" sudo make install >> ../env_setup.log 2>&1 cp php.ini-production php.ini -EXTENSION_DIR=`php-config --extension-dir` +EXTENSION_DIR=`bash -c 'php-config --extension-dir'` echo "extension=$EXTENSION_DIR/sqlsrv.so" >> php.ini echo "extension=$EXTENSION_DIR/pdo_sqlsrv.so" >> php.ini sudo cp php.ini /usr/local/lib diff --git a/test/Performance/setup_env_windows.ps1 b/test/Performance/setup_env_windows.ps1 index 2ac0d766..c4a580e5 100644 --- a/test/Performance/setup_env_windows.ps1 +++ b/test/Performance/setup_env_windows.ps1 @@ -19,6 +19,11 @@ IF($PHP_THREAD -ne "nts" -And $PHP_THREAD -ne "ts"){ Break } +IF($PHP_VERSION -NotMatch "7.[0-1].[0-9]"){ + Write-Host "PHP_VERSION must be in format of 7.x.x" + Break +} + $startingDir=$pwd.Path $tempFolder=Join-Path $startingDir "temp" @@ -104,6 +109,7 @@ Copy-Item C:\php-sdk\phpdev\vc14\$ARCH\deps\bin\libeay32.dll C:\Windows -force cd $startingDir [Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\php\", [System.EnvironmentVariableTarget]::Machine) +$env:Path += ";C:\php\" RefreshEnv wget https://getcomposer.org/installer -O composer-setup.php php composer-setup.php From 482d819aae647e8a53de2a3760528ff7d6210b13 Mon Sep 17 00:00:00 2001 From: ulvii Date: Fri, 14 Jul 2017 11:05:23 -0700 Subject: [PATCH 42/48] README update --- test/Performance/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/Performance/README.md b/test/Performance/README.md index 2108db71..416e6ea5 100644 --- a/test/Performance/README.md +++ b/test/Performance/README.md @@ -21,9 +21,12 @@ PHPBench is used to run the benchmarks. Visit http://phpbench.readthedocs.io/en/ ### 1. Modify lib/connect.php with the test database credetials ### 2. Execute run-perf_tests.py. +### Windows + py.exe run-perf_tests.py -platform -iterations -iterations-large -result-server -result-db -result-uid -result-pwd -iterations -iterations-large -result-server -result-db -result-uid -result-pwd + python3 run-perf_tests.py -platform -iterations -iterations-large -result-server -result-db -result-uid -result-pwd `-platform` - The platform that the tests are ran on. Must be one of the following: Windows10, WidnowsServer2016 WindowsServer2012 Ubuntu16 RedHat7 Sierra `-iterations` - The number of iterations for regular tests. From 36ba05800dfcd9eec59b87ece28939c8392eecbf Mon Sep 17 00:00:00 2001 From: ulvii Date: Fri, 14 Jul 2017 12:06:47 -0700 Subject: [PATCH 43/48] Fixing pip3 package name for redhat --- test/Performance/setup_env_unix.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Performance/setup_env_unix.sh b/test/Performance/setup_env_unix.sh index c1ffc10a..2f060892 100644 --- a/test/Performance/setup_env_unix.sh +++ b/test/Performance/setup_env_unix.sh @@ -55,7 +55,7 @@ elif [ $PLATFORM = "RedHat7" ]; then yes | sudo yum install python34-setuptools -y >> env_setup.log 2>&1 echo "OK" echo "Installing gcc, git, zip libxml, openssl, EPEL, python3, pip3..." - yes | sudo yum install -y gcc-c++ libxml2-devel git zip openssl-devel python34 python34-devel python3-pip >> env_setup.log 2>&1 + yes | sudo yum install -y gcc-c++ libxml2-devel git zip openssl-devel python34 python34-devel python34-pip >> env_setup.log 2>&1 echo "OK" echo "Installing MSODBCSQL..." curl -s https://packages.microsoft.com/config/rhel/7/prod.repo > /etc/yum.repos.d/mssql-release.repo From 7f3e1ded3937e159630db1c9c2047ccced1b5481 Mon Sep 17 00:00:00 2001 From: ulvii Date: Fri, 14 Jul 2017 13:45:03 -0700 Subject: [PATCH 44/48] Changing the way we get extension_dir becuase of the issues on RedHat --- test/Performance/setup_env_unix.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Performance/setup_env_unix.sh b/test/Performance/setup_env_unix.sh index 2f060892..9a2df0ec 100644 --- a/test/Performance/setup_env_unix.sh +++ b/test/Performance/setup_env_unix.sh @@ -49,7 +49,7 @@ elif [ $PLATFORM = "RedHat7" ]; then echo "OK" echo "Enabling EPEL repo..." wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm >> env_setup.log 2>&1 - yes | sudo yum install epel-release-latest-7.noarch.rpm >> env_setup.log 2>&1 + yes | sudo yum install epel-release-latest-7.noarch.rpm >> env_setup.log 2>&1 || true echo "OK" echo "Installing python34-setuptools..." yes | sudo yum install python34-setuptools -y >> env_setup.log 2>&1 @@ -120,7 +120,7 @@ make >> ../env_setup.log 2>&1 echo "OK" sudo make install >> ../env_setup.log 2>&1 cp php.ini-production php.ini -EXTENSION_DIR=`bash -c 'php-config --extension-dir'` +EXTENSION_DIR=`php -i | grep -m1 extension_dir | cut -f3 -d " "` echo "extension=$EXTENSION_DIR/sqlsrv.so" >> php.ini echo "extension=$EXTENSION_DIR/pdo_sqlsrv.so" >> php.ini sudo cp php.ini /usr/local/lib From b427670181a0fc053168d78a04cafa5b716f8f84 Mon Sep 17 00:00:00 2001 From: ulvii Date: Fri, 14 Jul 2017 14:25:59 -0700 Subject: [PATCH 45/48] Removing extension_dir --- test/Performance/setup_env_unix.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/Performance/setup_env_unix.sh b/test/Performance/setup_env_unix.sh index 9a2df0ec..e8a139dc 100644 --- a/test/Performance/setup_env_unix.sh +++ b/test/Performance/setup_env_unix.sh @@ -120,9 +120,8 @@ make >> ../env_setup.log 2>&1 echo "OK" sudo make install >> ../env_setup.log 2>&1 cp php.ini-production php.ini -EXTENSION_DIR=`php -i | grep -m1 extension_dir | cut -f3 -d " "` -echo "extension=$EXTENSION_DIR/sqlsrv.so" >> php.ini -echo "extension=$EXTENSION_DIR/pdo_sqlsrv.so" >> php.ini +echo "extension=sqlsrv.so" >> php.ini +echo "extension=pdo_sqlsrv.so" >> php.ini sudo cp php.ini /usr/local/lib cd .. php -v From c844e9c76bd4e06705296fce25ce9b0a899aded5 Mon Sep 17 00:00:00 2001 From: Yuki Wong Date: Fri, 14 Jul 2017 16:38:56 -0700 Subject: [PATCH 46/48] Update README.md Fix weird quotes --- test/Performance/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Performance/README.md b/test/Performance/README.md index 416e6ea5..b83d96a0 100644 --- a/test/Performance/README.md +++ b/test/Performance/README.md @@ -9,9 +9,9 @@ Run `cmd` as administrator. .\setup_env_windows.ps1 ### Ubuntu 16 - sudo env “PATH=$PATH” bash setup_env_unix.sh Ubuntu16 + sudo env "PATH=$PATH" bash setup_env_unix.sh Ubuntu16 ### RedHat 7 - sudo env “PATH=$PATH” bash setup_env_unix.sh RedHat7 + sudo env "PATH=$PATH" bash setup_env_unix.sh RedHat7 ### Sierra `brew` cannot be run with `sudo` on Sierra. Either enable passwordless `sudo` on the machine or enter the password when prompted. From 98f1d6a84bf7afa7490ab3ad08daacf04d305b2a Mon Sep 17 00:00:00 2001 From: ulvii Date: Fri, 14 Jul 2017 16:44:03 -0700 Subject: [PATCH 47/48] Update README.md --- test/Performance/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Performance/README.md b/test/Performance/README.md index b83d96a0..deb0e34b 100644 --- a/test/Performance/README.md +++ b/test/Performance/README.md @@ -19,7 +19,7 @@ Run `cmd` as administrator. ## Run benchmarks PHPBench is used to run the benchmarks. Visit http://phpbench.readthedocs.io/en/latest/introduction.html to have an idea how the tool works. -### 1. Modify lib/connect.php with the test database credetials +### 1. Modify lib/connect.php with the test database credentials ### 2. Execute run-perf_tests.py. ### Windows py.exe run-perf_tests.py -platform -iterations -iterations-large -result-server -result-db -result-uid -result-pwd -iterations -iterations-large -result-server -result-db -result-uid -result-pwd -`-platform` - The platform that the tests are ran on. Must be one of the following: Windows10, WidnowsServer2016 WindowsServer2012 Ubuntu16 RedHat7 Sierra +`-platform` - The platform that the tests are ran on. Must be one of the following: Windows10, WindowsServer2016 WindowsServer2012 Ubuntu16 RedHat7 Sierra `-iterations` - The number of iterations for regular tests. `-iterations-large` - The number of iterations for the tests that fetch large data. Usually set to 1. `-result-server` - The server of result database. It is assumed that, the result database already setup before running the tests. From 3f7348f6d6991d0d2447b48a2e749088dd3986b0 Mon Sep 17 00:00:00 2001 From: ulvii Date: Fri, 14 Jul 2017 16:44:31 -0700 Subject: [PATCH 48/48] Update connect.php --- test/Performance/lib/connect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Performance/lib/connect.php b/test/Performance/lib/connect.php index a35108c1..9dcd4bb3 100644 --- a/test/Performance/lib/connect.php +++ b/test/Performance/lib/connect.php @@ -1,6 +1,6 @@