-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #173 from moufmouf/perf-tests
Adding PHPBench performance test
- Loading branch information
Showing
7 changed files
with
347 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#!/bin/bash | ||
|
||
export DB_DRIVER=pdo_mysql | ||
export DB_HOST=localhost | ||
export DB_PORT=3306 | ||
export DB_USERNAME=root | ||
#export DB_ADMIN_USERNAME=root | ||
export DB_PASSWORD= | ||
export DB_NAME=tdbm_benchmark | ||
|
||
vendor/bin/phpbench |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"bootstrap": "vendor/autoload.php", | ||
"path": "tests/Performance" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
<?php | ||
|
||
|
||
namespace TheCodingMachine\TDBM; | ||
|
||
use Doctrine\Common\EventManager; | ||
use Doctrine\DBAL\Connection; | ||
use Doctrine\DBAL\DriverManager; | ||
use Doctrine\DBAL\Event\Listeners\OracleSessionInit; | ||
use function strtoupper; | ||
|
||
class ConnectionFactory | ||
{ | ||
/** | ||
* Resets the database and returns a (root) connection | ||
*/ | ||
public static function resetDatabase( | ||
string $dbDriver, | ||
?string $dbHost = null, | ||
?string $dbPort = null, | ||
?string $dbUserName = null, | ||
?string $dbAdminUserName = null, | ||
?string $dbPassword = null, | ||
?string $dbName = null | ||
): Connection { | ||
$config = new \Doctrine\DBAL\Configuration(); | ||
|
||
$dbDriver = $dbDriver; | ||
|
||
if ($dbDriver === 'pdo_sqlite') { | ||
$dbConnection = self::getConnection(); | ||
$dbConnection->exec('PRAGMA foreign_keys = ON;'); | ||
} elseif ($dbDriver === 'oci8') { | ||
$connectionParams = array( | ||
'servicename' => 'XE', | ||
'user' => $dbAdminUserName, | ||
// Because of issues in DBAL, admin and normal user password have to be the same. | ||
'password' => $dbPassword, | ||
'host' => $dbHost, | ||
'port' => $dbPort, | ||
'driver' => $dbDriver, | ||
'dbname' => $dbAdminUserName, | ||
'charset' => 'AL32UTF8', | ||
); | ||
|
||
$adminConn = DriverManager::getConnection($connectionParams, $config); | ||
|
||
// When dropAndCreateDatabase is run several times, Oracle can have some issues releasing the TDBM user. | ||
// Let's forcefully delete the connection! | ||
$adminConn->exec("select 'alter system kill session ''' || sid || ',' || serial# || ''';' from v\$session where username = '".strtoupper($dbName)."'"); | ||
|
||
$adminConn->getSchemaManager()->dropAndCreateDatabase($dbName); | ||
|
||
$dbConnection = self::getConnection(); | ||
} else { | ||
$connectionParams = array( | ||
'user' => $dbUserName, | ||
'password' => $dbPassword, | ||
'host' => $dbHost, | ||
'port' => $dbPort, | ||
'driver' => $dbDriver, | ||
); | ||
|
||
$adminConn = DriverManager::getConnection($connectionParams, $config); | ||
|
||
$adminConn->getSchemaManager()->dropAndCreateDatabase($dbName); | ||
|
||
$connectionParams['dbname'] = $dbName; | ||
|
||
$dbConnection = DriverManager::getConnection($connectionParams, $config); | ||
} | ||
|
||
return $dbConnection; | ||
} | ||
|
||
public static function createConnection( | ||
string $dbDriver, | ||
?string $dbHost = null, | ||
?string $dbPort = null, | ||
?string $dbUserName = null, | ||
?string $dbPassword = null, | ||
?string $dbName = null | ||
): Connection { | ||
$config = new \Doctrine\DBAL\Configuration(); | ||
|
||
$dbDriver = $dbDriver; | ||
|
||
if ($dbDriver === 'pdo_sqlite') { | ||
$connectionParams = array( | ||
'memory' => true, | ||
'driver' => 'pdo_sqlite', | ||
); | ||
$dbConnection = DriverManager::getConnection($connectionParams, $config); | ||
} elseif ($dbDriver === 'oci8') { | ||
$evm = new EventManager(); | ||
$evm->addEventSubscriber(new OracleSessionInit(array( | ||
'NLS_TIME_FORMAT' => 'HH24:MI:SS', | ||
'NLS_DATE_FORMAT' => 'YYYY-MM-DD HH24:MI:SS', | ||
'NLS_TIMESTAMP_FORMAT' => 'YYYY-MM-DD HH24:MI:SS', | ||
))); | ||
|
||
$connectionParams = array( | ||
'servicename' => 'XE', | ||
'user' => $dbUserName, | ||
'password' => $dbPassword, | ||
'host' => $dbHost, | ||
'port' => $dbPort, | ||
'driver' => $dbDriver, | ||
'dbname' => $dbName, | ||
'charset' => 'AL32UTF8', | ||
); | ||
$dbConnection = DriverManager::getConnection($connectionParams, $config, $evm); | ||
$dbConnection->setAutoCommit(true); | ||
} else { | ||
$connectionParams = array( | ||
'user' => $dbUserName, | ||
'password' => $dbPassword, | ||
'host' => $dbHost, | ||
'port' => $dbPort, | ||
'driver' => $dbDriver, | ||
'dbname' => $dbName, | ||
); | ||
$dbConnection = DriverManager::getConnection($connectionParams, $config); | ||
} | ||
|
||
return $dbConnection; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
<?php | ||
|
||
|
||
namespace TheCodingMachine\TDBM\Performance; | ||
|
||
use Doctrine\Common\Cache\ArrayCache; | ||
use Doctrine\DBAL\Connection; | ||
use Mouf\Database\SchemaAnalyzer\SchemaAnalyzer; | ||
use PhpBench\Benchmark\Metadata\Annotations\Iterations; | ||
use TheCodingMachine\FluidSchema\TdbmFluidSchema; | ||
use TheCodingMachine\TDBM\Configuration; | ||
use TheCodingMachine\TDBM\ConfigurationInterface; | ||
use TheCodingMachine\TDBM\ConnectionFactory; | ||
use TheCodingMachine\TDBM\DummyGeneratorListener; | ||
use TheCodingMachine\TDBM\TDBMAbstractServiceTest; | ||
use TheCodingMachine\TDBM\TDBMSchemaAnalyzer; | ||
use TheCodingMachine\TDBM\TDBMService; | ||
use TheCodingMachine\TDBM\Test\Dao\UserDao; | ||
use TheCodingMachine\TDBM\Utils\PathFinder\PathFinder; | ||
use TheCodingMachine\TDBM\Utils\TDBMDaoGenerator; | ||
use function dirname; | ||
use function getenv; | ||
use function glob; | ||
use function is_dir; | ||
use function is_file; | ||
use function rmdir; | ||
use function rtrim; | ||
use function unlink; | ||
|
||
/** | ||
* @BeforeClassMethods({"initDatabase"}) | ||
*/ | ||
class ManyToOneBench | ||
{ | ||
public static function initDatabase(): void | ||
{ | ||
$dbConnection = ConnectionFactory::resetDatabase( | ||
getenv('DB_DRIVER') ?: null, | ||
getenv('DB_HOST') ?: null, | ||
getenv('DB_PORT') ?: null, | ||
getenv('DB_USERNAME') ?: null, | ||
getenv('DB_ADMIN_USERNAME') ?: null, | ||
getenv('DB_PASSWORD') ?: null, | ||
getenv('DB_NAME') ?: null | ||
); | ||
|
||
self::initSchema($dbConnection); | ||
|
||
self::generateDaosAndBeans($dbConnection); | ||
} | ||
|
||
private static function initSchema(Connection $connection): void | ||
{ | ||
$fromSchema = $connection->getSchemaManager()->createSchema(); | ||
$toSchema = clone $fromSchema; | ||
|
||
$db = new TdbmFluidSchema($toSchema, new \TheCodingMachine\FluidSchema\DefaultNamingStrategy($connection->getDatabasePlatform())); | ||
|
||
$db->table('countries') | ||
->column('id')->integer()->primaryKey() | ||
->column('label')->string(255)->unique(); | ||
|
||
$db->table('users') | ||
->column('id')->integer()->primaryKey() | ||
->column('name')->string(255) | ||
->column('country_id')->references('countries'); | ||
|
||
$sqlStmts = $toSchema->getMigrateFromSql($fromSchema, $connection->getDatabasePlatform()); | ||
|
||
foreach ($sqlStmts as $sqlStmt) { | ||
$connection->exec($sqlStmt); | ||
} | ||
|
||
for ($i = 1; $i<200; $i++) { | ||
TDBMAbstractServiceTest::insert($connection, 'countries', [ | ||
'id' => $i, | ||
'label' => 'Country '.$i, | ||
]); | ||
} | ||
|
||
for ($i = 1; $i<1000; $i++) { | ||
TDBMAbstractServiceTest::insert($connection, 'users', [ | ||
'id' => $i, | ||
'name' => 'User '.$i, | ||
'country_id' => ($i%199) +1, | ||
]); | ||
} | ||
} | ||
|
||
private static function generateDaosAndBeans(Connection $connection): void | ||
{ | ||
$schemaManager = $connection->getSchemaManager(); | ||
$schemaAnalyzer = new SchemaAnalyzer($schemaManager); | ||
$tdbmSchemaAnalyzer = new TDBMSchemaAnalyzer($connection, new ArrayCache(), $schemaAnalyzer); | ||
$tdbmDaoGenerator = new TDBMDaoGenerator(self::createConfiguration(), $tdbmSchemaAnalyzer); | ||
$rootPath = __DIR__ . '/../'; | ||
self::recursiveDelete(__DIR__. '/../../src/Test/Dao/'); | ||
|
||
$tdbmDaoGenerator->generateAllDaosAndBeans(); | ||
} | ||
|
||
/** | ||
* Delete a file or recursively delete a directory. | ||
* | ||
* @param string $str Path to file or directory | ||
* @return bool | ||
*/ | ||
private static function recursiveDelete(string $str): bool | ||
{ | ||
if (is_file($str)) { | ||
return @unlink($str); | ||
} elseif (is_dir($str)) { | ||
$scan = glob(rtrim($str, '/') . '/*'); | ||
foreach ($scan as $index => $path) { | ||
self::recursiveDelete($path); | ||
} | ||
|
||
return @rmdir($str); | ||
} | ||
return false; | ||
} | ||
|
||
private function getConnection(): Connection | ||
{ | ||
return ConnectionFactory::createConnection( | ||
getenv('DB_DRIVER') ?: null, | ||
getenv('DB_HOST') ?: null, | ||
getenv('DB_PORT') ?: null, | ||
getenv('DB_USERNAME') ?: null, | ||
getenv('DB_PASSWORD') ?: null, | ||
getenv('DB_NAME') ?: null | ||
); | ||
} | ||
|
||
protected function getTdbmService(): TDBMService | ||
{ | ||
return new TDBMService($this->getConfiguration()); | ||
} | ||
|
||
private static $cache; | ||
|
||
protected static function getCache(): ArrayCache | ||
{ | ||
if (self::$cache === null) { | ||
self::$cache = new ArrayCache(); | ||
} | ||
return self::$cache; | ||
} | ||
|
||
private static function createConfiguration(): ConfigurationInterface | ||
{ | ||
$configuration = new Configuration('TheCodingMachine\\TDBM\\Test\\Dao\\Bean', 'TheCodingMachine\\TDBM\\Test\\Dao', self::getConnection(), null, self::getCache(), null, null, []); | ||
$configuration->setPathFinder(new PathFinder(null, dirname(__DIR__, 5))); | ||
return $configuration; | ||
} | ||
|
||
/** | ||
* @var ConfigurationInterface | ||
*/ | ||
private $configuration; | ||
|
||
protected function getConfiguration() : ConfigurationInterface | ||
{ | ||
if ($this->configuration === null) { | ||
return self::createConfiguration(); | ||
} | ||
return $this->configuration; | ||
} | ||
|
||
/** | ||
* @Iterations(10) | ||
*/ | ||
public function benchManyToOne(): void | ||
{ | ||
$tdbmService = $this->getTdbmService(); | ||
$userDao = new UserDao($tdbmService); | ||
foreach ($userDao->findAll() as $user) { | ||
$label = $user->getCountry()->getLabel(); | ||
} | ||
} | ||
} |
Oops, something went wrong.