Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Extensions
Benchmarktools
Commits
f1e37dc4
Commit
f1e37dc4
authored
Mar 15, 2022
by
VangelisP
Browse files
Initial release
parents
Changes
18
Expand all
Hide whitespace changes
Inline
Side-by-side
CRM/Benchmarktools/BAO/Benchmarktools.php
0 → 100644
View file @
f1e37dc4
<?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
;
}
}
CRM/Benchmarktools/BAO/Databasebenchmarks.php
0 → 100644
View file @
f1e37dc4
<?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
;
}
}
CRM/Benchmarktools/BAO/ReportTests.php
0 → 100644
View file @
f1e37dc4
<?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
;
}
}
CRM/Benchmarktools/Page/Benchmarkresults.php
0 → 100644
View file @
f1e37dc4
<?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