Commit f1e37dc4 authored by VangelisP's avatar VangelisP
Browse files

Initial release

parents
<?php
class CRM_Benchmarktools_BAO_Benchmarktools {
/**
* getRandomNames
*
* Helper function to output random names into an array
*
* @param mixed $count
* @return void
*/
public static function getRandomNames($count = 1) {
$intCount = 0;
$data = [];
while ($intCount < $count) {
$randomName = self::randomNameGenerator();
$row = [
'first_name' => $randomName['first_name'],
'last_name' => $randomName['last_name'],
];
// Generate data
$data[] = $row;
$intCount++;
}
// End
return $data;
}
/**
* randomNameGenerator
*
* Helper function to generate random names
*
* @return void
*/
public static function randomNameGenerator() {
$data = [];
$firstname = [
'Johnathon',
'Anthony',
'Erasmo',
'Raleigh',
'Nancie',
'Tama',
'Camellia',
'Augustine',
'Christeen',
'Luz',
'Diego',
'Lyndia',
'Thomas',
'Georgianna',
'Leigha',
'Alejandro',
'Marquis',
'Joan',
'Stephania',
'Elroy',
'Zonia',
'Buffy',
'Sharie',
'Blythe',
'Gaylene',
'Elida',
'Randy',
'Margarete',
'Margarett',
'Dion',
'Tomi',
'Arden',
'Clora',
'Laine',
'Becki',
'Margherita',
'Bong',
'Jeanice',
'Qiana',
'Lawanda',
'Rebecka',
'Maribel',
'Tami',
'Yuri',
'Michele',
'Rubi',
'Larisa',
'Lloyd',
'Tyisha',
'Samatha',
];
$lastname = [
'Mischke',
'Serna',
'Pingree',
'Mcnaught',
'Pepper',
'Schildgen',
'Mongold',
'Wrona',
'Geddes',
'Lanz',
'Fetzer',
'Schroeder',
'Block',
'Mayoral',
'Fleishman',
'Roberie',
'Latson',
'Lupo',
'Motsinger',
'Drews',
'Coby',
'Redner',
'Culton',
'Howe',
'Stoval',
'Michaud',
'Mote',
'Menjivar',
'Wiers',
'Paris',
'Grisby',
'Noren',
'Damron',
'Kazmierczak',
'Haslett',
'Guillemette',
'Buresh',
'Center',
'Kucera',
'Catt',
'Badon',
'Grumbles',
'Antes',
'Byron',
'Volkman',
'Klemp',
'Pekar',
'Pecora',
'Schewe',
'Ramage',
];
$data['first_name'] = $firstname[rand(0, count($firstname) - 1)];
$data['last_name'] = $lastname[rand(0, count($lastname) - 1)];
return $data;
}
/**
* checkExtensionInstalled
*
* @param mixed $key
* @return void
*/
public static function checkExtensionInstalled($key) {
$installed = FALSE;
$result = civicrm_api3('Extension', 'get', [
'key' => $key,
]);
if ($result['count'] == 1) {
// We got the key, now lets check if it is installed
$extID = $result['id'];
if ($result['values'][$extID]['status'] == 'installed') {
$installed = TRUE;
}
}
return $installed;
}
/**
* exportRecords
* Exports the records into a CSV file
*
* @param mixed $title
* @param mixed $data
* @return void
*/
public static function exportRecords($title, $data) {
$separator = ';';
$config = CRM_Core_Config::singleton();
$resPath = $config->configAndLogDir;
$resFile = $resPath . "benchmark_job_results_" . date('Ymd') . ".csv";
// Get server URL
$serverURL = parse_url(CIVICRM_UF_BASEURL, PHP_URL_HOST);
// If the file is not there, lets create a header first
if (!file_exists($resFile)) {
$header = [
'timestamp',
'benchmark',
'process_time_(in_seconds)',
'count',
'server_url',
];
file_put_contents($resFile, implode($separator, $header) . PHP_EOL, FILE_APPEND);
}
// Proceed with the actual data
$outputCSV = [
'timestamp' => date('Y-m-d H:i:s'),
'title' => $title,
'process_time' => $data['process_time'],
'count' => (!empty($data['count']) ? $data['count'] : 0),
'server_url' => $serverURL,
];
file_put_contents($resFile, implode($separator, $outputCSV) . PHP_EOL, FILE_APPEND);
}
public static function showConsoleOutput($string, $showOutput) {
if ($showOutput) {
print $string . PHP_EOL;
}
return;
}
}
<?php
use CRM_Benchmarktools_BAO_Benchmarktools as B;
class CRM_Benchmarktools_BAO_Databasebenchmarks {
public static $tableName = "benchmarktools_table";
/**
* runTest
*
* This is the main function that is responsible for the actual mysql tests
*
* @param mixed $type
* @param mixed $count
* @return void
*/
public static function runTest($type, $count = 1) {
$tableName = self::$tableName;
// Create the table but drop it if it exists
self::tableOperations('drop');
self::tableOperations('create');
$insertStatement = "INSERT INTO {$tableName} (first_name, last_name) ";
$data = B::getRandomNames($count);
if ($type == 'single') {
// Single inserts of x counts
$insertData = self::convertToInsert($data, $insertStatement, 'single');
}
elseif ($type == 'massive') {
// Batch inserts of x counts
$insertData = self::convertToInsert($data, $insertStatement, 'massive');
}
// Count the statistics
$starttime = microtime(TRUE);
foreach ($insertData as $insertStatus) {
CRM_Core_DAO::executeQuery($insertStatus);
}
$stepTime = microtime(TRUE);
$execTime = number_format((float) ($stepTime - $starttime), 3);
$results = [
'process_time' => $execTime,
'type' => $type,
'count' => $count,
];
// Finish, drop the table
self::tableOperations('drop');
return $results;
}
/**
* getRandomReads
*
* Based on https://www.warpconduit.net/2011/03/23/selecting-a-random-record-using-mysql-benchmark-results/ , we use this function
* to measure how fast we can do X SELECT statements
*
* @param mixed $count
* @return void
*/
public static function getRandomReads($count) {
$intCount = 0;
$tableName = self::$tableName;
$results = $avgCount = [];
// Number of random records to generate, if too high (eg 1M), it will cause a `max_allowed_packet` error
$generateContacts = 500000;
// Prepare the tables
self::tableOperations('drop');
self::tableOperations('create');
// Prepare the random data
$insertStatement = "INSERT INTO {$tableName} (first_name, last_name) ";
$data = B::getRandomNames($generateContacts);
$insertData = self::convertToInsert($data, $insertStatement, 'massive');
foreach ($insertData as $insertStatus) {
CRM_Core_DAO::executeQuery($insertStatus);
}
// Random reads of count X
// We use this query below, taken from https://www.warpconduit.net/2011/03/23/selecting-a-random-record-using-mysql-benchmark-results/
// Credits go to this fella
$randomReadSQL = "SELECT * FROM {$tableName} WHERE RAND()<(SELECT ((1/COUNT(*))*10) FROM {$tableName}) ORDER BY RAND() LIMIT 1";
$starttime = microtime(TRUE);
while ($intCount < $count) {
CRM_Core_DAO::executeQuery($randomReadSQL);
$intCount++;
}
$stepTime = microtime(TRUE);
$execTime = number_format((float) ($stepTime - $starttime), 3);
$results = [
'process_time' => $execTime,
'type' => 'random read',
'count' => $count,
];
// Finished, drop the table
self::tableOperations('drop');
return $results;
}
/**
* tableOperations
*
* Helper function to create or drop the custom table
*
* @param mixed $mode
* @return void
*/
public static function tableOperations($mode) {
$tableName = self::$tableName;
switch ($mode) {
case 'create':
$tableDDL = "
CREATE TABLE {$tableName} (
id INT auto_increment NOT NULL,
first_name varchar(100) NULL,
last_name varchar(100) NULL,
primary key (id),
INDEX (id)
)
ENGINE=InnoDB";
break;
case 'drop':
$tableDDL = "DROP TABLE IF EXISTS {$tableName}";
break;
}
CRM_Core_DAO::executeQuery($tableDDL);
return;
}
/**
* convertToInsert
*
* Helper function that converts array to insert statements
*
* @param mixed $data
* @param mixed $insertHeader
* @param mixed $type
* @return void
*/
public static function convertToInsert($data, $insertHeader, $type) {
$insertStatement = NULL;
$insertLine = $output = [];
if ($type == 'single') {
//$insertStatement = $insertHeader . "VALUES\n";
foreach ($data as $row) {
$insertStatement = $insertHeader . "VALUES ('{$row['first_name']}', '{$row['last_name']}')\n";
$output[] = $insertStatement;
}
}
elseif ($type == 'massive') {
$insertStatement = $insertHeader . "VALUES\n";
foreach ($data as $row) {
$insertLine[] = " ('{$row['first_name']}', '{$row['last_name']}')";
}
$insertStatement .= implode(",\n", $insertLine) . ';';
$output[] = $insertStatement;
}
return $output;
}
}
<?php
class CRM_Benchmarktools_BAO_ReportTests {
/**
* compileReport
*
* Function that will render a report internally so that we can measure how long it took to produce it
*
* @param mixed $reportClass
* @return void
*/
public static function compileReport($reportClass) {
$outputData = [];
$starttime = microtime(TRUE);
$inputParams = NULL;
$obj = self::getReportObject($reportClass, $inputParams);
$queryParams = $obj->getParams();
// Modify query params
$obj->setParams($queryParams);
$sql = $obj->buildQuery(TRUE);
// Dirty way to alter the query
// TODO: Fix it properly, need to investigate $queryParams
$stripString = "AND (`contact_civireport`.`id` IS NULL OR (`contact_civireport`.`id` IN (SELECT contact_id FROM civicrm_acl_contact_cache WHERE user_id = 0)))";
$sql = str_replace($stripString, "", $sql);
if ($reportClass == 'CRM_Report_Form_Contact_Summary') {
$stripLimit = "LIMIT 0, 50";
$sql = str_replace($stripLimit, "", $sql);
}
if ($reportClass == 'CRM_Report_Form_Contribute_Summary') {
$stripLimit = "LIMIT 0, 50";
$sql = str_replace($stripLimit, "", $sql);
$badCurrency = "contribution_civireport.contribution_status_id, currency";
$goodCurrency = "contribution_civireport.contribution_status_id, civicrm_contribution_currency";
$sql = str_replace($badCurrency, $goodCurrency, $sql);
}
// Continue
$rows = [];
$obj->buildRows($sql, $rows);
$stepTime = microtime(TRUE);
$execTime = number_format((float) ($stepTime - $starttime), 3);
$outputData['build_rows'] = $execTime;
$obj->formatDisplay($rows);
$stepTime = microtime(TRUE);
$execTime = number_format((float) ($stepTime - $starttime), 3);
$outputData['formatDisplay'] = $execTime;
$rowCount = count($rows);
$outputData['row_count'] = $rowCount;
$stepTime = microtime(TRUE);
$execTime = number_format((float) ($stepTime - $starttime), 3);
$outputData['process_time'] = $execTime;
return $outputData;
}
/**
* getReportObject
*
* @param mixed $reportClass
* @param mixed $inputParams
* @return void
*/
public function getReportObject($reportClass, $inputParams) {
$config = CRM_Core_Config::singleton();
$config->keyDisable = TRUE;
$controller = new CRM_Core_Controller_Simple($reportClass, ts('some title'));
$tmpReportVal = explode('_', $reportClass);
$reportName = array_pop($tmpReportVal);
$reportObj =& $controller->_pages[$reportName];
$tmpGlobals = [];
$tmpGlobals['_REQUEST']['force'] = 1;
$tmpGlobals['_GET'][$config->userFrameworkURLVar] = 'civicrm/placeholder';
$tmpGlobals['_SERVER']['QUERY_STRING'] = '';
if (!empty($inputParams['fields'])) {
$fields = implode(',', $inputParams['fields']);
$tmpGlobals['_GET']['fld'] = $fields;
$tmpGlobals['_GET']['ufld'] = 1;
}
if (!empty($inputParams['filters'])) {
foreach ($inputParams['filters'] as $key => $val) {
$tmpGlobals['_GET'][$key] = $val;
}
}
if (!empty($inputParams['group_bys'])) {
$groupByFields = implode(' ', $inputParams['group_bys']);
$tmpGlobals['_GET']['gby'] = $groupByFields;
}
CRM_Utils_GlobalStack::singleton()->push($tmpGlobals);
try {
$reportObj->storeResultSet();
$reportObj->buildForm();
}
catch (Exception $e) {
// print_r($e->getCause()->getUserInfo());
CRM_Utils_GlobalStack::singleton()->pop();
throw $e;
}
CRM_Utils_GlobalStack::singleton()->pop();
return $reportObj;
}
}
<?php
use CRM_Benchmarktools_ExtensionUtil as E;
class CRM_Benchmarktools_Page_Benchmarkresults extends CRM_Core_Page {
public function run() {
$validFile = $emptyLog = FALSE;
$config = CRM_Core_Config::singleton();
// Get page actions
$action = CRM_Utils_Request::retrieve('action', 'String', $this);
$downloadFileName = CRM_Utils_Request::retrieve('filename', 'String', $this, FALSE, 0);
if ($downloadFileName && !empty($action) && $action == CRM_Core_Action::VIEW) {
$mimeType = 'text/csv';
$path = $config->configAndLogDir . $downloadFileName;
if (file_exists($path)) {
$buffer = file_get_contents($path);
$validFile = TRUE;
}
else {
$validFile = FALSE;
$urlRedirect = CRM_Utils_System::url('civicrm/admin/benchmark/results?reset=1');
CRM_Core_Error::statusBounce(
E::ts('It appears that the file is non-existing or unreadable'),
$urlRedirect
);
}
if ($validFile) {
CRM_Utils_System::download(
CRM_Utils_File::cleanFileName(basename($downloadFileName)),
$mimeType,
$buffer,
NULL,
TRUE,
'inline'
);
}
}
elseif ($downloadFileName && !empty($action) && $action == CRM_Core_Action::DELETE) {
$path = $config->configAndLogDir . $downloadFileName;
if (file_exists($path)) {
// Make sure that the file is actually a CSV extension
$path_parts = pathinfo($path);
if ($path_parts['extension'] == 'csv') {
// Do the file deletion and redirect
$validFile = TRUE;
}
if ($validFile) {
if (!unlink($path)) {
CRM_Core_Session::setStatus(E::ts('Unable to delete file %1', ['1' => $downloadFileName]), 'File deletion failed', 'error');
}
else {
CRM_Core_Session::setStatus(E::ts('File %1 deleted successfully', ['1' => $downloadFileName]), 'File deletion successful', 'success');
}
CRM_Utils_System::redirect(
CRM_Utils_System::url('civicrm/admin/benchmark/results?reset=1')
);
}
else {
$urlRedirect = CRM_Utils_System::url('civicrm/admin/benchmark/results?reset=1');
CRM_Core_Error::statusBounce(
E::ts('It appears that the file is non-existing or unreadable'),
$urlRedirect
);
}
}
else {
$urlRedirect = CRM_Utils_System::url('civicrm/admin/benchmark/results?reset=1');
CRM_Core_Error::statusBounce(
E::ts('It appears that the file is non-existing or unreadable'),
$urlRedirect
);
}
}
$fTimeStamp = '-';
$benchmarkFiles = $config->configAndLogDir;
// Grab the REST services
$csv_files = glob($benchmarkFiles . "/benchmark_job_results_*.{csv,txt,log}", GLOB_BRACE);
$pattern = "/_([0-9].*)\.csv$/";
// Reform the array but first check if it's empty
if (empty($csv_files)) {
$csv_opts = [];
$emptyLog = TRUE;
}
else {
foreach ($csv_files as $csv_key => $csv_file) {
$csv_opts[$csv_file]['basename'] = basename($csv_file);
// Extract the timestamp
preg_match_all($pattern, $csv_opts[$csv_file]['basename'], $matches);
if (array_key_exists('1', $matches)) {
$extractedDate = $matches[1][0];
$fTimeStamp = date("Y-m-d", strtotime($extractedDate));
}
$csv_opts[$csv_file]['timestamp'] = $fTimeStamp;
}
}