Skip to content

Commit

Permalink
Merge pull request #173 from moufmouf/perf-tests
Browse files Browse the repository at this point in the history
Adding PHPBench performance test
  • Loading branch information
moufmouf committed Sep 9, 2019
2 parents 7f9e22f + 432db0a commit 63c78c0
Show file tree
Hide file tree
Showing 7 changed files with 347 additions and 91 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ vendor/*
/.travis/
/vendor-bin/require-checker/vendor/
/vendor-bin/couscous/vendor/
.phpunit.result.cache
.phpunit.result.cache
/phpbench.sh
/xdebug/
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@
"thecodingmachine/tdbm-fluid-schema-builder": "^1.0.0",
"phpstan/phpstan": "^0.11.5",
"thecodingmachine/phpstan-strict-rules": "^0.11.0",
"bamarni/composer-bin-plugin": "^1.2"
"bamarni/composer-bin-plugin": "^1.2",
"phpbench/phpbench": "^0.16.10"
},
"conflict": {
"mouf/database.tdbm": "~5.0.0"
Expand Down
11 changes: 11 additions & 0 deletions phpbench.dist.sh
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
4 changes: 4 additions & 0 deletions phpbench.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"bootstrap": "vendor/autoload.php",
"path": "tests/Performance"
}
128 changes: 128 additions & 0 deletions tests/ConnectionFactory.php
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;
}
}
181 changes: 181 additions & 0 deletions tests/Performance/ManyToOneBench.php
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();
}
}
}
Loading

0 comments on commit 63c78c0

Please sign in to comment.