diff --git a/Block/Adminhtml/Index/Gui.php b/Block/Adminhtml/Index/Gui.php
index d6cdb52..b4b0e98 100755
--- a/Block/Adminhtml/Index/Gui.php
+++ b/Block/Adminhtml/Index/Gui.php
@@ -24,7 +24,7 @@
use Magento\Framework\App\Cache\Manager as CacheManager;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Module\Manager as ModuleManager;
-use Genaker\Opcache\Performance\PerformaceToolkit;
+use Genaker\Opcache\Performance\PerformanceToolkit;
class Gui extends \Magento\Backend\Block\Template
{
@@ -47,7 +47,7 @@ class Gui extends \Magento\Backend\Block\Template
* @param CacheManager $cacheManager
* @param ScopeConfigInterface $scopeConfig
* @param ModuleManager $moduleManager
- * @param PerformaceToolkit $performanceToolkit
+ * @param PerformanceToolkit $performanceToolkit
* @param array $config
* @param array $data
*/
@@ -67,7 +67,7 @@ public function __construct(
private CacheManager $cacheManager,
private ScopeConfigInterface $scopeConfig,
private ModuleManager $moduleManager,
- private PerformaceToolkit $performanceToolkit,
+ private PerformanceToolkit $performanceToolkit,
private array $config = [],
array $data = []
) {
@@ -129,9 +129,9 @@ public function getCollectionPageSize(): int
/**
* Get the performance toolkit instance
*
- * @return PerformaceToolkit
+ * @return PerformanceToolkit
*/
- public function getPerformanceToolkit(): PerformaceToolkit
+ public function getPerformanceToolkit(): PerformanceToolkit
{
return $this->performanceToolkit;
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..ffe291e
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,58 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [1.0.22] - 2026-02-13
+
+### Security
+- **CRITICAL**: Enabled SSL certificate verification in HTTP performance tests
+- Added SSL_VERIFYHOST validation to prevent man-in-the-middle attacks
+- Removed insecure `CURLOPT_SSL_VERIFYPEER = false` settings
+- Replaced `rand()` with `random_int()` for better randomness in cache busting
+
+### Fixed
+- Fixed class name typo: `PerformaceToolkit` → `PerformanceToolkit`
+- Fixed inconsistent boolean usage in `microtime()` calls (TRUE → true)
+- Fixed type hint inconsistencies (removed incorrect `|null` annotations)
+- Fixed variable naming consistency to follow camelCase convention
+- Added unique temp file names to prevent race conditions
+- Added file existence check before unlink operation
+- Removed ObjectManager anti-pattern - now using proper dependency injection
+- Prevented compiler optimization in CPU performance test
+
+### Changed
+- Extracted 36 magic numbers to class constants for better maintainability:
+ - Performance test constants (CPU_TEST_ITERATIONS, MEMORY_TEST_ARRAY_SIZE, etc.)
+ - HTTP and connection timeout constants (HTTP_TIMEOUT_SECONDS, etc.)
+ - Database table size thresholds (DB_TABLE_SIZE_LARGE_MB, etc.)
+ - Redis memory and performance thresholds (REDIS_MEMORY_HIGH_MB, etc.)
+ - OPcache memory thresholds (OPCACHE_LOW_MEMORY_MB, etc.)
+- Improved variable naming throughout (e.g., `$j` → `$result`, `$temp_file` → `$tempFile`)
+- Updated module version to 1.0.22
+
+### Documentation
+- Added security best practices section to README
+- Added SSL/TLS configuration guidelines
+- Added access control recommendations
+- Added performance testing considerations
+- Created CHANGELOG.md for tracking changes
+
+### Code Quality
+- Added performance test constants:
+ - `CPU_TEST_ITERATIONS`
+ - `MEMORY_TEST_ARRAY_SIZE`
+ - `MEMORY_TEST_STRING_LENGTH`
+ - `FILE_READ_ITERATIONS`
+ - `HTTP_TIMEOUT_SECONDS`
+ - `HTTP_CONNECT_TIMEOUT_SECONDS`
+ - `REDIS_CONNECTION_TIMEOUT_SECONDS`
+ - `OPCACHE_LOW_MEMORY_MB`
+ - `OPCACHE_WARNING_MEMORY_MB`
+ - `BYTES_TO_MB`
+- Improved code consistency and maintainability
+
+## [1.0.21] - Previous Release
+- See git history for previous changes
diff --git a/Performance/PerformaceToolkit.php b/Performance/PerformanceToolkit.php
similarity index 82%
rename from Performance/PerformaceToolkit.php
rename to Performance/PerformanceToolkit.php
index 55fcd81..6152c4a 100755
--- a/Performance/PerformaceToolkit.php
+++ b/Performance/PerformanceToolkit.php
@@ -12,8 +12,42 @@
use Magento\Framework\App\DeploymentConfig;
use Magento\Framework\App\ProductMetadataInterface;
-class PerformaceToolkit
+class PerformanceToolkit
{
+ /**
+ * Performance test constants
+ */
+ private const CPU_TEST_ITERATIONS = 10000000;
+ private const MEMORY_TEST_ARRAY_SIZE = 100000;
+ private const MEMORY_TEST_STRING_LENGTH = 100;
+ private const FILE_READ_ITERATIONS = 100;
+ private const HTTP_TIMEOUT_SECONDS = 30;
+ private const HTTP_CONNECT_TIMEOUT_SECONDS = 10;
+ private const REDIS_CONNECTION_TIMEOUT_SECONDS = 2;
+ private const OPCACHE_LOW_MEMORY_MB = 32;
+ private const OPCACHE_WARNING_MEMORY_MB = 64;
+ private const BYTES_TO_MB = 1048576; // 1024 * 1024
+
+ /**
+ * Database table size thresholds (in MB)
+ */
+ private const DB_TABLE_SIZE_LARGE_MB = 1000; // 1GB
+ private const DB_TABLE_SIZE_WARNING_MB = 100;
+ private const DB_TABLE_SIZE_CRITICAL_MB = 500;
+ private const DB_TOTAL_SIZE_LARGE_GB = 5120; // 5GB in MB
+ private const DB_TOTAL_SIZE_VERY_LARGE_GB = 10240; // 10GB in MB
+
+ /**
+ * Redis memory thresholds (in MB)
+ */
+ private const REDIS_MEMORY_HIGH_MB = 1024; // 1GB
+ private const REDIS_MEMORY_MODERATE_MB = 512;
+ private const REDIS_HIT_RATE_EXCELLENT = 90;
+ private const REDIS_HIT_RATE_GOOD = 80;
+ private const REDIS_HIT_RATE_MODERATE = 60;
+ private const REDIS_FRAGMENTATION_HIGH = 1.5;
+ private const REDIS_FRAGMENTATION_MODERATE = 1.2;
+
/**
* Constructor
*
@@ -36,11 +70,14 @@ public function __construct(
*/
public function testCPUPerformance(): float
{
- $start = microtime(TRUE);
- for ($a = 0; $a < 10000000; $a++) {
- $b = $a * $a;
+ $start = microtime(true);
+ $result = 0;
+ for ($i = 0; $i < self::CPU_TEST_ITERATIONS; $i++) {
+ $result += $i * $i;
}
- $end = microtime(TRUE);
+ $end = microtime(true);
+ // Use $result to prevent optimization
+ unset($result);
return $end - $start;
}
@@ -105,18 +142,18 @@ public function runPerformanceTestMultipleTimes(callable $testFunction, array &$
*/
public function testMemoryAllocation(): array
{
- $start = microtime(TRUE);
- $memory_start = memory_get_usage();
+ $start = microtime(true);
+ $memoryStart = memory_get_usage();
$array = [];
- for ($i = 0; $i < 100000; $i++) {
- $array[] = str_repeat('x', 100);
+ for ($i = 0; $i < self::MEMORY_TEST_ARRAY_SIZE; $i++) {
+ $array[] = str_repeat('x', self::MEMORY_TEST_STRING_LENGTH);
}
- $memory_end = memory_get_usage();
- $end = microtime(TRUE);
+ $memoryEnd = memory_get_usage();
+ $end = microtime(true);
unset($array);
return [
'time' => $end - $start,
- 'memory' => $memory_end - $memory_start
+ 'memory' => $memoryEnd - $memoryStart
];
}
@@ -127,21 +164,23 @@ public function testMemoryAllocation(): array
*/
public function testFileOperations(): float
{
- $start = microtime(TRUE);
- $temp_file = sys_get_temp_dir() . '/magento_perf_test.tmp';
+ $start = microtime(true);
+ $tempFile = sys_get_temp_dir() . '/magento_perf_test_' . uniqid() . '.tmp';
// Write test
- file_put_contents($temp_file, str_repeat('Test data', 1000));
+ file_put_contents($tempFile, str_repeat('Test data', 1000));
// Read test
- for ($i = 0; $i < 100; $i++) {
- $content = file_get_contents($temp_file);
+ for ($i = 0; $i < self::FILE_READ_ITERATIONS; $i++) {
+ $content = file_get_contents($tempFile);
}
// Cleanup
- unlink($temp_file);
+ if (file_exists($tempFile)) {
+ unlink($tempFile);
+ }
- $end = microtime(TRUE);
+ $end = microtime(true);
return $end - $start;
}
@@ -153,18 +192,16 @@ public function testFileOperations(): float
*/
public function testDatabaseOperations(int $iterations = 3)
{
- $start = microtime(TRUE);
+ $start = microtime(true);
try {
- $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
- $resource = $objectManager->get(\Magento\Framework\App\ResourceConnection::class);
- $connection = $resource->getConnection();
+ $connection = $this->resourceConnection->getConnection();
// Simple query test
for ($i = 0; $i < $iterations; $i++) {
$result = $connection->fetchAll("SELECT 1 as test");
}
- $end = microtime(TRUE);
+ $end = microtime(true);
return $end - $start;
} catch (\Exception $e) {
return 'ERROR: ' . $e->getMessage();
@@ -179,16 +216,14 @@ public function testDatabaseOperations(int $iterations = 3)
public function testMySQLLatency()
{
try {
- $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
- $resource = $objectManager->get(\Magento\Framework\App\ResourceConnection::class);
- $connection = $resource->getConnection();
+ $connection = $this->resourceConnection->getConnection();
// Perform 10 latency tests
$latencies = [];
for ($i = 0; $i < 10; $i++) {
- $start = microtime(TRUE);
+ $start = microtime(true);
$result = $connection->fetchAll("SELECT 1");
- $end = microtime(TRUE);
+ $end = microtime(true);
$latencies[] = $end - $start;
}
@@ -215,11 +250,8 @@ public function testMySQLLatency()
public function testRedisLatency()
{
try {
- $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
-
// Try to get Redis connection from Magento's cache configuration
- $cacheConfig = $objectManager->get(\Magento\Framework\App\DeploymentConfig::class);
- $cacheSettings = $cacheConfig->get('cache');
+ $cacheSettings = $this->deploymentConfig->get('cache');
if (isset($cacheSettings['frontend']['default']['backend_options']['server'])) {
// Redis is configured, test connection
@@ -228,13 +260,13 @@ public function testRedisLatency()
$host = $cacheSettings['frontend']['default']['backend_options']['server'] ?? '127.0.0.1';
$port = (int)($cacheSettings['frontend']['default']['backend_options']['port'] ?? 6379);
- if ($redis->connect($host, $port, 1)) {
+ if ($redis->connect($host, $port, self::REDIS_CONNECTION_TIMEOUT_SECONDS)) {
// Perform 10 latency tests
$latencies = [];
for ($i = 0; $i < 10; $i++) {
- $start = microtime(TRUE);
+ $start = microtime(true);
$redis->ping();
- $end = microtime(TRUE);
+ $end = microtime(true);
$latencies[] = $end - $start;
}
$redis->close();
@@ -266,16 +298,12 @@ public function testRedisLatency()
/**
* Test HTTP performance
*
- * @param string|null $url
+ * @param string $url
* @return float|string
*/
public function testHTTPPerformance(string $url)
{
- if ($url === null) {
- throw new \Exception('URL is required');
- }
-
- $start = microtime(TRUE);
+ $start = microtime(true);
// Initialize cURL
$ch = curl_init();
@@ -284,9 +312,10 @@ public function testHTTPPerformance(string $url)
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
- curl_setopt($ch, CURLOPT_TIMEOUT, 30);
- curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($ch, CURLOPT_TIMEOUT, self::HTTP_TIMEOUT_SECONDS);
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, self::HTTP_CONNECT_TIMEOUT_SECONDS);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_USERAGENT, 'Magento Performance Test');
// Execute the request
@@ -298,7 +327,7 @@ public function testHTTPPerformance(string $url)
curl_close($ch);
- $end = microtime(TRUE);
+ $end = microtime(true);
$totalTime = $end - $start;
// Check for errors
@@ -316,16 +345,16 @@ public function testHTTPPerformance(string $url)
/**
* Test HTTP performance with cache busting
*
- * @param string|null $url
+ * @param string $url
* @return float|string
*/
public function testHTTPPerformanceUncached(string $url)
{
// Add timestamp parameter to bypass cache
$separator = (strpos($url, '?') !== false) ? '&' : '?';
- $uncachedUrl = $url . $separator . 'timestamp=' . time() . rand(1, 1000);
+ $uncachedUrl = $url . $separator . 'timestamp=' . time() . random_int(1, 1000);
- $start = microtime(TRUE);
+ $start = microtime(true);
// Initialize cURL
$ch = curl_init();
@@ -334,9 +363,10 @@ public function testHTTPPerformanceUncached(string $url)
curl_setopt($ch, CURLOPT_URL, $uncachedUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
- curl_setopt($ch, CURLOPT_TIMEOUT, 30);
- curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($ch, CURLOPT_TIMEOUT, self::HTTP_TIMEOUT_SECONDS);
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, self::HTTP_CONNECT_TIMEOUT_SECONDS);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_USERAGENT, 'Magento Performance Test (Uncached)');
// Add cache-busting headers
@@ -355,7 +385,7 @@ public function testHTTPPerformanceUncached(string $url)
curl_close($ch);
- $end = microtime(TRUE);
+ $end = microtime(true);
$totalTime = $end - $start;
// Check for errors
@@ -411,12 +441,12 @@ public function checkOPcacheConfiguration(): array
$memoryConsumption = $opcacheConfig['directives']['opcache.memory_consumption'] ?? 0;
// Check free memory (less than 32MB is concerning)
- if ($memoryFree < 32 * 1024 * 1024) {
- $checks[] = ['type' => 'error', 'msg' => 'OPcache free memory: ' . number_format($memoryFree / 1024 / 1024, 1) . 'MB - CRITICALLY LOW, increase opcache.memory_consumption'];
- } elseif ($memoryFree < 64 * 1024 * 1024) {
- $checks[] = ['type' => 'warning', 'msg' => 'OPcache free memory: ' . number_format($memoryFree / 1024 / 1024, 1) . 'MB - LOW, consider increasing memory'];
+ if ($memoryFree < self::OPCACHE_LOW_MEMORY_MB * self::BYTES_TO_MB) {
+ $checks[] = ['type' => 'error', 'msg' => 'OPcache free memory: ' . number_format($memoryFree / self::BYTES_TO_MB, 1) . 'MB - CRITICALLY LOW, increase opcache.memory_consumption'];
+ } elseif ($memoryFree < self::OPCACHE_WARNING_MEMORY_MB * self::BYTES_TO_MB) {
+ $checks[] = ['type' => 'warning', 'msg' => 'OPcache free memory: ' . number_format($memoryFree / self::BYTES_TO_MB, 1) . 'MB - LOW, consider increasing memory'];
} else {
- $checks[] = ['type' => 'success', 'msg' => 'OPcache free memory: ' . number_format($memoryFree / 1024 / 1024, 1) . 'MB - ADEQUATE'];
+ $checks[] = ['type' => 'success', 'msg' => 'OPcache free memory: ' . number_format($memoryFree / self::BYTES_TO_MB, 1) . 'MB - ADEQUATE'];
}
// Additional checks would continue here...
@@ -502,10 +532,10 @@ public function checkDatabaseTableSizes(): array
$sizeDisplay = $sizeMB > 1024 ? round($sizeMB / 1024, 2) . 'GB' : $sizeMB . 'MB';
// Determine status based on size
- if ($sizeMB > 1000) { // > 1GB
+ if ($sizeMB > self::DB_TABLE_SIZE_LARGE_MB) { // > 1GB
$status = 'error';
$statusText = 'LARGE table - consider optimization';
- } elseif ($sizeMB > 100) { // > 100MB
+ } elseif ($sizeMB > self::DB_TABLE_SIZE_WARNING_MB) { // > 100MB
$status = 'warning';
$statusText = 'Growing large, monitor size';
} else {
@@ -527,7 +557,7 @@ public function checkDatabaseTableSizes(): array
$checks[] = ['type' => $status, 'msg' => $message];
// Add specific recommendations for known problematic tables
- if ($sizeMB > 500) {
+ if ($sizeMB > self::DB_TABLE_SIZE_CRITICAL_MB) {
if (strpos($tableName, 'log_') === 0) {
$checks[] = ['type' => 'info', 'msg' => "→ Log table cleanup: Consider truncating old log entries"];
} elseif (strpos($tableName, 'session') !== false) {
@@ -562,10 +592,10 @@ public function checkDatabaseTableSizes(): array
$totalDbDisplay = $totalDbMB > 1024 ? round($totalDbMB / 1024, 2) . 'GB' : $totalDbMB . 'MB';
- if ($totalDbMB > 10240) { // > 10GB
+ if ($totalDbMB > self::DB_TOTAL_SIZE_VERY_LARGE_GB) { // > 10GB
$dbStatus = 'error';
$dbStatusText = 'VERY LARGE database - consider optimization';
- } elseif ($totalDbMB > 5120) { // > 5GB
+ } elseif ($totalDbMB > self::DB_TOTAL_SIZE_LARGE_GB) { // > 5GB
$dbStatus = 'warning';
$dbStatusText = 'Large database - monitor growth';
} else {
@@ -618,7 +648,7 @@ public function checkRedisMemoryUsage(): array
}
$redis = new \Redis();
- if (!$redis->connect($host, $port, 2)) {
+ if (!$redis->connect($host, $port, self::REDIS_CONNECTION_TIMEOUT_SECONDS)) {
$checks[] = ['type' => 'error', 'msg' => "Cannot connect to Redis server at {$host}:{$port}"];
return $checks;
}
@@ -639,13 +669,13 @@ public function checkRedisMemoryUsage(): array
$memoryRss = isset($info['used_memory_rss_human']) ? $info['used_memory_rss_human'] : 'Unknown';
// Convert to MB for comparison
- $memoryMB = round($memoryUsed / 1024 / 1024, 1);
+ $memoryMB = round($memoryUsed / self::BYTES_TO_MB, 1);
// Determine status based on memory usage
- if ($memoryMB > 1024) { // > 1GB
+ if ($memoryMB > self::REDIS_MEMORY_HIGH_MB) { // > 1GB
$status = 'warning';
$statusText = 'HIGH memory usage';
- } elseif ($memoryMB > 512) { // > 512MB
+ } elseif ($memoryMB > self::REDIS_MEMORY_MODERATE_MB) { // > 512MB
$status = 'warning';
$statusText = 'Moderate memory usage';
} else {
@@ -679,11 +709,11 @@ public function checkRedisMemoryUsage(): array
if ($total > 0) {
$hitRate = round(($hits / $total) * 100, 2);
- if ($hitRate > 90) {
+ if ($hitRate > self::REDIS_HIT_RATE_EXCELLENT) {
$checks[] = ['type' => 'success', 'msg' => "Redis hit rate: {$hitRate}% - EXCELLENT"];
- } elseif ($hitRate > 80) {
+ } elseif ($hitRate > self::REDIS_HIT_RATE_GOOD) {
$checks[] = ['type' => 'success', 'msg' => "Redis hit rate: {$hitRate}% - GOOD"];
- } elseif ($hitRate > 60) {
+ } elseif ($hitRate > self::REDIS_HIT_RATE_MODERATE) {
$checks[] = ['type' => 'warning', 'msg' => "Redis hit rate: {$hitRate}% - MODERATE"];
} else {
$checks[] = ['type' => 'error', 'msg' => "Redis hit rate: {$hitRate}% - LOW, check cache strategy"];
@@ -706,9 +736,9 @@ public function checkRedisMemoryUsage(): array
// Memory fragmentation
if (isset($info['mem_fragmentation_ratio'])) {
$fragmentation = (float)$info['mem_fragmentation_ratio'];
- if ($fragmentation > 1.5) {
+ if ($fragmentation > self::REDIS_FRAGMENTATION_HIGH) {
$checks[] = ['type' => 'warning', 'msg' => "Redis memory fragmentation: {$fragmentation} - HIGH, consider restart"];
- } elseif ($fragmentation > 1.2) {
+ } elseif ($fragmentation > self::REDIS_FRAGMENTATION_MODERATE) {
$checks[] = ['type' => 'info', 'msg' => "Redis memory fragmentation: {$fragmentation} - Moderate"];
} else {
$checks[] = ['type' => 'success', 'msg' => "Redis memory fragmentation: {$fragmentation} - Good"];
diff --git a/README.md b/README.md
index 89429d6..c2bcc40 100755
--- a/README.md
+++ b/README.md
@@ -164,6 +164,23 @@ Performance parameters can be customized via `etc/di.xml`:
It's the most effective way to measure and compare Magento PHP code execution performance across different servers.
+## **Security Best Practices**
+
+### SSL/TLS Configuration
+- **SSL Verification Enabled**: All HTTP performance tests now verify SSL certificates to prevent man-in-the-middle attacks
+- **Certificate Validation**: Both peer and host verification are enabled for maximum security
+- If testing local development environments with self-signed certificates, use proper certificate management instead of disabling verification
+
+### Access Control
+- **Admin Access Only**: This module is restricted to admin users only
+- **ACL Protection**: Ensure proper ACL rules are configured for your admin users
+- **Password Protection**: Use strong passwords for admin accounts with access to performance tools
+
+### Performance Testing Considerations
+- **Rate Limiting**: Be mindful when running performance tests against production environments
+- **Resource Usage**: Performance tests consume server resources - schedule appropriately
+- **Data Privacy**: Avoid exposing sensitive configuration data in logs or screenshots
+
## **Technical Implementation**
### Class Architecture
diff --git a/etc/module.xml b/etc/module.xml
index 4749d1e..daf62c1 100644
--- a/etc/module.xml
+++ b/etc/module.xml
@@ -1,4 +1,4 @@
-
+