Skip to content

Commit

Permalink
Validation performance test
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-vostrikov committed Oct 5, 2020
1 parent 9906265 commit 6ff0a0a
Show file tree
Hide file tree
Showing 6 changed files with 313 additions and 1 deletion.
128 changes: 128 additions & 0 deletions app/Console/ValidationController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php

namespace App\Console;

use Yii;
use App\Model\DataForm;

class ValidationController extends \yii\console\Controller
{
public function actionInsertApp($needError)
{
$needError = (int)$needError;
$data = $this->generateData($needError);

$form = new DataForm();

if ($form->load($data, '') && $form->validate()) {
$this->saveData($data, 'data_for_validation_app');

} else {
echo implode("\n", $form->getErrorSummary(false)) . "\n";
}
}

public function actionInsertDb($needValidData)
{
$needValidData = (int)$needValidData;
$data = $this->generateData($needValidData);
try {
$this->saveData($data, 'data_for_validation_db');

} catch (\yii\db\Exception $e) {
$errorMsg = $e->errorInfo[2];
if ($e->errorInfo[1] === 3819) {
preg_match("/Check constraint 'chk_(.*)' is violated/", $errorMsg, $matches);
$field = $matches[1];
echo "Field '" . $field . "'" . ' is incorrect' . "\n";
} elseif ($e->errorInfo[1] === 1292) {
preg_match("/Incorrect .* value: '.*' for column '(.*)'/", $errorMsg, $matches);
$field = $matches[1];
echo "Field '" . $field . "'" . ' is incorrect' . "\n";
} else {
echo $e;
}

return;
}
}

public function generateData($needError)
{
$data = [
'name' => $this->randomString() . ' ' . $this->randomString(),
'login' => $this->randomString(),
'email' => $this->randomString() . '@example.com',
'password' => $this->randomString(8, 64),
'agreed' => rand(0, 1),
'date' => date('Y-m-d H:i:s', time() - rand(0, 86400 - 1)),
'ipv4' => implode('.', [rand(0, 255), rand(0, 255), rand(0, 255), rand(0, 255)]),
'guid' => implode('-', [$this->randomHex(8), $this->randomHex(4), '4' . $this->randomHex(3), '8' . $this->randomHex(3), $this->randomHex(12)]),
];

$incorrectData = [
'name' => $this->randomString() . $this->randomString(),
'login' => '#' . rand(100000000, 999999999),
'email' => $this->randomString(),
'password' => $this->randomString(4, 6),
'agreed' => rand(10, 20),
'date' => $this->randomString(),
'ipv4' => $this->randomString(),
'guid' => $this->randomString(),
];

if ($needError) {
$fields = array_keys($data);
$field = $fields[rand(0, count($fields) - 1)];
$data[$field] = $incorrectData[$field];
}

return $data;
}

protected $letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
protected $hexDigits = '0123456789ABCDEF';

protected function randomString($minLen = 1, $maxLen = 30)
{
$len = rand($minLen, $maxLen);
$str = '';
for ($i = 0; $i < $len; $i++) {
$ch = $this->letters[rand(0, strlen($this->letters) - 1)];
$str .= $ch;
}

return $str;
}

protected function randomHex($len)
{
$str = '';
for ($i = 0; $i < $len; $i++) {
$ch = $this->hexDigits[rand(0, strlen($this->hexDigits) - 1)];
$str .= $ch;
}

return $str;
}


public function saveData($data, $tbl)
{
$sql = "
INSERT INTO {$tbl}(`name`, `login`, `email`, `password`, `agreed`, `date`, `ipv4`, `guid`)
VALUES (:name, :login, :email, :password, :agreed, :date, :ipv4, :guid)
";
$params = [
':name' => $data['name'],
':login' => $data['login'],
':email' => $data['email'],
':password' => $data['password'],
':agreed' => $data['agreed'],
':date' => $data['date'],
':ipv4' => $data['ipv4'],
':guid' => $data['guid'],
];
\Yii::$app->db->createCommand($sql, $params)->execute();
}
}
88 changes: 88 additions & 0 deletions app/Console/ValidationPerformanceTestController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

namespace App\Console;

use App\Model\DataForm;
use App\Model\Document;
use App\Model\CurrentStock;

class ValidationPerformanceTestController extends PerformanceTestController
{
protected $testingTime = 10;
protected $emulateDocumentPage = false;
protected $usleepTimeout = 100;

protected function resetData()
{
\Yii::$app->db->createCommand('DELETE FROM data_for_validation_app')->execute();
\Yii::$app->db->createCommand('DELETE FROM data_for_validation_db')->execute();
}

protected function generateActionParams()
{
$needError = (rand(0, 999) >= 950);

return [$needError, 0];
}

public function actionRunApp()
{
$this->runPerformanceTest('validation/insert-app');
}

public function actionRunDb()
{
$this->runPerformanceTest('validation/insert-db');
}

public function actionRunPureCalls($callNumber = 600)
{
$controller = new ValidationController('validation', $this->module);

$this->resetData();

$startTime = microtime(true);
for ($i = 0; $i < $callNumber; $i++) {
if ($i % 10 === 0) {
echo $i . "\r";
}

list($needError, $stub) = $this->generateActionParams();

ob_start();
$controller->actionInsertApp($needError);
ob_get_clean();
}
$stopTime = microtime(true);
$timeDiff = $stopTime - $startTime;

echo 'App:' . "\n";
echo 'Call number: ' . $callNumber . "\n";
echo 'Total time: ' . $timeDiff . "\n";
echo 'Calls per second: ' . ($callNumber / $timeDiff) . "\n";


echo "\n";
$this->resetData();

$startTime = microtime(true);
for ($i = 0; $i < $callNumber; $i++) {
if ($i % 10 === 0) {
echo $i . "\r";
}

list($needError, $stub) = $this->generateActionParams();

ob_start();
$controller->actionInsertDb($needError);
ob_get_clean();
}
$stopTime = microtime(true);
$timeDiff = $stopTime - $startTime;

echo 'DB:' . "\n";
echo 'Call number: ' . $callNumber . "\n";
echo 'Total time: ' . $timeDiff . "\n";
echo 'Calls per second: ' . ($callNumber / $timeDiff) . "\n";
}
}
30 changes: 30 additions & 0 deletions app/Model/DataForm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace App\Model;

class DataForm extends \yii\base\Model
{
public $name;
public $login;
public $email;
public $password;
public $agreed;
public $date;
public $ipv4;
public $guid;

public function rules()
{
return [
[['name'], 'match', 'pattern' => '/^[A-Za-z]+\s[A-Za-z]+$/u'],
[['login'], 'match', 'pattern' => '/^[a-zA-Z0-9\-_]+$/'],
[['email'], 'email'],
[['email', 'password'], 'required'],
[['password'], 'string', 'length' => [8, 64]],
[['agreed'], 'boolean'],
[['date'], 'datetime', 'format' => 'php:Y-m-d H:i:s'],
[['ipv4'], 'ip', 'ipv6' => false],
[['guid'], 'match', 'pattern' => '/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i'],
];
}
}
11 changes: 11 additions & 0 deletions app/Model/Material.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace App\Model;

class Material extends \App\Db\ActiveRecord
{
public static function tableName()
{
return 'materials';
}
}
2 changes: 1 addition & 1 deletion app/config/main-local.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=stocks',
'dsn' => 'mysql:host=127.0.0.1;dbname=stocks',
'username' => 'user',
'password' => 'password',
'charset' => 'utf8',
Expand Down
55 changes: 55 additions & 0 deletions app/migrations/m201004_163540_validation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

use yii\db\Migration;

/**
* Class m201004_163540_validation
*/
class m201004_163540_validation extends Migration
{
public function up()
{
$this->createTable('data_for_validation_app', [
'id' => $this->primaryKey(),
'name' => $this->string()->null(),
'login' => $this->string()->null(),
'email' => $this->string()->notNull(),
'password' => $this->string()->notNull(),
'agreed' => $this->boolean()->null(),
'date' => $this->dateTime()->null(),
'ipv4' => $this->string()->null(),
'guid' => $this->string()->null(),
]);

$this->createTable('data_for_validation_db', [
'id' => $this->primaryKey(),
'name' => $this->string()->null(),
'login' => $this->string()->null(),
'email' => $this->string()->notNull(),
'password' => $this->string()->notNull(),
'agreed' => $this->boolean()->null(),
'date' => $this->dateTime()->null(),
'ipv4' => $this->string()->null(),
'guid' => $this->string()->null(),
]);

$sql = "
ALTER TABLE data_for_validation_db
ADD CONSTRAINT chk_name CHECK (name REGEXP '^[A-Za-z]+ [A-Za-z]+$'),
ADD CONSTRAINT chk_login CHECK (login REGEXP '^[a-zA-Z0-9\-_]+$'),
ADD CONSTRAINT chk_email CHECK (email REGEXP :email_pattern),
ADD CONSTRAINT chk_password CHECK (LENGTH(password) BETWEEN 8 AND 64),
ADD CONSTRAINT chk_agreed CHECK (agreed BETWEEN 0 AND 1),
ADD CONSTRAINT chk_ipv4 CHECK (ipv4 REGEXP '^(?:(?:2(?:[0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9])\.){3}(?:(?:2([0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9]))$'),
ADD CONSTRAINT chk_guid CHECK (guid REGEXP '^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$')
";

$this->execute($sql, [':email_pattern' => trim((new \yii\validators\EmailValidator())->pattern, '/')]);
}

public function down()
{
$this->dropTable('data_for_validation_db');
$this->dropTable('data_for_validation_app');
}
}

0 comments on commit 6ff0a0a

Please sign in to comment.