-
-
Save matipojo/f425185ad12d9cc628163120f2b99640 to your computer and use it in GitHub Desktop.
| <?php | |
| class CommentsVsConstantsPerformanceTest { | |
| const ITERATIONS = 1000000; | |
| const WARMUP_ROUNDS = 3; | |
| const TEST_FILES = [ | |
| 'raw' => 'raw_values.php', | |
| 'constants' => 'constants.php' | |
| ]; | |
| private function createTestFiles(): void { | |
| // Create file with raw values | |
| $rawCode = <<<'EOD' | |
| <?php | |
| function processUserRaw() { | |
| // User status codes | |
| // 0 = inactive | |
| // 1 = active | |
| // 2 = suspended | |
| // 3 = pending | |
| $status = 1; | |
| // Maximum login attempts | |
| $maxAttempts = 3; | |
| // Default timeout in seconds | |
| $timeout = 1800; | |
| // Account types | |
| // 'free' = Free tier | |
| // 'pro' = Professional tier | |
| // 'enterprise' = Enterprise tier | |
| $accountType = 'pro'; | |
| if ($status === 1 && $maxAttempts > 0) { | |
| return $accountType === 'pro' ? $timeout * 2 : $timeout; | |
| } | |
| return null; | |
| } | |
| EOD; | |
| file_put_contents(self::TEST_FILES['raw'], $rawCode); | |
| // Create file with constants | |
| $constantsCode = <<<'EOD' | |
| <?php | |
| class UserConfig { | |
| const STATUS_INACTIVE = 0; | |
| const STATUS_ACTIVE = 1; | |
| const STATUS_SUSPENDED = 2; | |
| const STATUS_PENDING = 3; | |
| const MAX_LOGIN_ATTEMPTS = 3; | |
| const SESSION_TIMEOUT_SECONDS = 1800; | |
| const ACCOUNT_FREE = 'free'; | |
| const ACCOUNT_PRO = 'pro'; | |
| const ACCOUNT_ENTERPRISE = 'enterprise'; | |
| } | |
| function processUserConstants() { | |
| $status = UserConfig::STATUS_ACTIVE; | |
| $maxAttempts = UserConfig::MAX_LOGIN_ATTEMPTS; | |
| $timeout = UserConfig::SESSION_TIMEOUT_SECONDS; | |
| $accountType = UserConfig::ACCOUNT_PRO; | |
| if ($status === UserConfig::STATUS_ACTIVE && $maxAttempts > 0) { | |
| return $accountType === UserConfig::ACCOUNT_PRO ? | |
| $timeout * 2 : $timeout; | |
| } | |
| return null; | |
| } | |
| EOD; | |
| file_put_contents(self::TEST_FILES['constants'], $constantsCode); | |
| } | |
| private function clearCache(): void { | |
| if (function_exists('opcache_reset')) { | |
| opcache_reset(); | |
| } | |
| } | |
| private function measureFileCompilation(string $filename): float { | |
| $this->clearCache(); | |
| $start = microtime(true); | |
| include $filename; | |
| $end = microtime(true); | |
| return $end - $start; | |
| } | |
| private function measureExecution(callable $callback): float { | |
| // Warmup phase | |
| for ($i = 0; $i < self::WARMUP_ROUNDS; $i++) { | |
| $callback(); | |
| } | |
| $start = microtime(true); | |
| for ($i = 0; $i < self::ITERATIONS; $i++) { | |
| $callback(); | |
| } | |
| $end = microtime(true); | |
| return $end - $start; | |
| } | |
| public function runComparison(): void { | |
| // Create test files | |
| $this->createTestFiles(); | |
| // Measure compilation times | |
| $rawCompileTime = $this->measureFileCompilation(self::TEST_FILES['raw']); | |
| $constantsCompileTime = $this->measureFileCompilation(self::TEST_FILES['constants']); | |
| // Measure execution times | |
| $rawExecutionTime = $this->measureExecution('processUserRaw'); | |
| $constantsExecutionTime = $this->measureExecution('processUserConstants'); | |
| // Calculate totals | |
| $rawTotal = $rawCompileTime + $rawExecutionTime; | |
| $constantsTotal = $constantsCompileTime + $constantsExecutionTime; | |
| // Print results | |
| echo "Performance Comparison Results:\n"; | |
| echo str_repeat("=", 60) . "\n"; | |
| echo "Raw Values Approach:\n"; | |
| echo sprintf(" Compilation Time: %.6f seconds\n", $rawCompileTime); | |
| echo sprintf(" Execution Time: %.6f seconds\n", $rawExecutionTime); | |
| echo sprintf(" Total Time: %.6f seconds\n", $rawTotal); | |
| echo str_repeat("-", 60) . "\n"; | |
| echo "Constants Approach:\n"; | |
| echo sprintf(" Compilation Time: %.6f seconds\n", $constantsCompileTime); | |
| echo sprintf(" Execution Time: %.6f seconds\n", $constantsExecutionTime); | |
| echo sprintf(" Total Time: %.6f seconds\n", $constantsTotal); | |
| echo str_repeat("=", 60) . "\n"; | |
| // Calculate and display differences | |
| $compileDiff = $constantsCompileTime - $rawCompileTime; | |
| $executionDiff = $constantsExecutionTime - $rawExecutionTime; | |
| $totalDiff = $constantsTotal - $rawTotal; | |
| echo "\nPerformance Analysis:\n"; | |
| echo sprintf("Compilation Difference: %+.6f seconds\n", $compileDiff); | |
| echo sprintf("Execution Difference: %+.6f seconds\n", $executionDiff); | |
| echo sprintf("Total Difference: %+.6f seconds\n", $totalDiff); | |
| echo "\nAnalysis Summary:\n"; | |
| echo "1. Compilation Impact:\n"; | |
| echo " - Constants approach " . ($compileDiff > 0 ? "takes longer" : "is faster") . " to compile\n"; | |
| echo " - Difference is " . number_format(abs($compileDiff * 1000000), 2) . " microseconds\n"; | |
| echo "\n2. Execution Impact:\n"; | |
| echo " - Constants approach " . ($executionDiff > 0 ? "takes longer" : "is faster") . " to execute\n"; | |
| echo " - Difference is " . number_format(abs($executionDiff * 1000000), 2) . " microseconds\n"; | |
| // Cleanup test files | |
| unlink(self::TEST_FILES['raw']); | |
| unlink(self::TEST_FILES['constants']); | |
| } | |
| } | |
| // Run the test | |
| $test = new CommentsVsConstantsPerformanceTest(); | |
| $test->runComparison(); |
matipojo
commented
Dec 26, 2024
It's very interesting, and obviously, lookup time has a price, but it's extremely negligible. This is not about efficiency but rather ease of maintenance. Most of the time, we maintain the code rather than write it—the easier it is to understand, the better.
In the next dev talk I will talk about this with regards to refactoring. Come to the meeting, I hope u will find it interesting.
Coding is hard, and reading code requires a lot of cognitive load, so I aim to help with that in my comment. It's a bigger issue, and I am ready to open it up some more.
But comments are still considered a code smell, and this is one of the pillars of Clean Code. The University teaches us to write comments, while the industry, with its savoir-faire, takes a different approach. At the end, when we understand all the issues, it boils down to style—clean code rules are basically a style.
P.s
Your amazing code does not take into account statistical caching that happens in runtime, as all interpreted languages have.