* All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is free * software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, or (at your option) any later version. * * The GNU General Public License can be found at * http://www.gnu.org/copyleft/gpl.html. * * This script is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * This copyright notice MUST APPEAR in all copies of the script! ****************************************************************************/ /***************************************************************************** * Tiny TYPO3 Test Suite v 1.0.0 * by: Michiel Roos * _______ * /_ __(_)___ __ __ * / / / / __ \/ / / / * / / / / / / / /_/ / * /_/ /_/_/ /_/\__, / * /____/ * ________ ______ ____ _____ * /_ __/\ \/ / __ \/ __ \__ / * / / \ / /_/ / / / //_ < * / / / / ____/ /_/ /__/ / * /_/ /_/_/ \____/____/ * ______ __ _____ _ __ * /_ __/__ _____/ /_ / ___/__ __(_) /____ * / / / _ \/ ___/ __/ \__ \/ / / / / __/ _ \ * / / / __(__ ) /_ ___/ / /_/ / / /_/ __/ * /_/ \___/____/\__/ /____/\__,_/_/\__/\___/ * * https://github.com/Tuurlijk/TinyTypo3TestSuite * ****************************************************************************/ /***************************************************************************** * Setup * * - testname: Displayed in the page title and page header * - runs : The default number of runs * - skipSets: An array of setNames to skip ****************************************************************************/ $testName = 'GeneralUtility::getFilesInDir'; $runs = 100; $skipSets = array(); /***************************************************************************** * Parameter Sets * * Define multiple parameter sets here so you can excersise the method well. * Each method needs a description. The other parameters must match the * parameter names of the method. ****************************************************************************/ $parameterSets = array( 'set1' => array ( 'description' => 'Regular use', 'path' => __DIR__ . '/../typo3temp/', 'extensionList' => 'js,css' ), 'set2' => array ( 'description' => 'Sort mtime, no prepend path', 'path' => __DIR__ . '/../typo3temp/', 'extensionList' => 'js,css', 'prependPath' => FALSE, 'order' => 'mtime' ), 'set3' => array ( 'description' => 'Sort mtime, prepend path', 'path' => __DIR__ . '/../typo3temp/', 'extensionList' => 'js,css', 'prependPath' => TRUE, 'order' => 'mtime' ), 'set4' => array ( 'description' => 'Sort 1, prepend path', 'path' => __DIR__ . '/../typo3temp/', 'extensionList' => 'js,css', 'prependPath' => TRUE, 'order' => 1 ), 'set5' => array ( 'description' => 'Sort 1, excludePattern', 'path' => __DIR__ . '/../typo3temp/', 'extensionList' => '', 'prependPath' => FALSE, 'order' => 1, 'excludePattern' => 'rtehtmlarea' ), ); /***************************************************************************** * Test Methods: * * Define your test methods here. Name them version1 - version[n]. * version1 must be the baseline implementation. ****************************************************************************/ $descriptions['version1'] = 'Baseline'; function version1($path, $extensionList = '', $prependPath = FALSE, $order = '', $excludePattern = '', $md5Index = FALSE) { // Initialize variables: $filearray = array(); $sortarray = array(); $path = rtrim($path, '/'); // Find files+directories: if (@is_dir($path)) { $extensionList = strtolower($extensionList); $d = dir($path); if (is_object($d)) { while ($entry = $d->read()) { if (@is_file(($path . '/' . $entry))) { $fI = pathinfo($entry); // Don't change this ever - extensions may depend on the fact that the hash is an md5 of the path! (import/export extension) $key = md5($path . '/' . $entry); if ((!strlen($extensionList) || inList($extensionList, strtolower($fI['extension']))) && (!strlen($excludePattern) || !preg_match(('/^' . $excludePattern . '$/'), $entry))) { $filearray[$key] = ($prependPath ? $path . '/' : '') . $entry; if ($order == 'mtime') { $sortarray[$key] = filemtime($path . '/' . $entry); } elseif ($order) { $sortarray[$key] = strtolower($entry); } } } } $d->close(); } else { return 'error opening path: "' . $path . '"'; } } // Sort them: if ($order) { asort($sortarray); $newArr = array(); foreach ($sortarray as $k => $v) { $newArr[$k] = $filearray[$k]; } $filearray = $newArr; } // Return result reset($filearray); return $filearray; } $descriptions['version2'] = 'Optimized Baseline'; function version2($path, $extensionList = '', $prependPath = FALSE, $order = '', $excludePattern = '', $md5Index = FALSE) { $extensionList = ',' . $extensionList . ','; $files = array(); $path = rtrim($path, '/'); $pathPrefix = $prependPath ? $path . '/' : ''; if (@is_dir($path)) { $directory = dir($path); if ($directory !== NULL && $directory !== FALSE) { while ($entry = $directory->read()) { if (@is_file(($path . '/' . $entry))) { if ( ((string)$extensionList === ',,' || stripos($extensionList, ',' . pathinfo($entry, PATHINFO_EXTENSION) . ',') !== FALSE) && ((string)$excludePattern === '' || !preg_match(('/^' . $excludePattern . '$/'), $entry)) ) { if ($order === 'mtime') { $files[$entry] = filemtime($path . '/' . $entry); } else { $files[] = $entry; } } } } $directory->close(); } else { return 'error opening path: "' . $path . '"'; } } switch ($order) { case 'mtime': asort($files); foreach ($files as $key => $entry) { // Don't change this ever - extensions may depend on the fact that the hash is an md5 of the path! (import/export extension) $files[md5($path . '/' . $key)] = $pathPrefix . $key; unset($files[$key]); } break; case 1: sort($files); default: foreach ($files as $key => $entry) { // Don't change this ever - extensions may depend on the fact that the hash is an md5 of the path! (import/export extension) $files[md5($path . '/' . $entry)] = $pathPrefix . $entry; unset($files[$key]); } } return $files; } $descriptions['version3'] = 'Using scandir( )'; function version3($path, $extensionList = '', $prependPath = FALSE, $order = '', $excludePattern = '', $md5Index = FALSE) { $extensionList = ',' . $extensionList . ','; $files = array(); $path = rtrim($path, '/'); $pathPrefix = $path . '/'; $valuePathPrefix = $prependPath ? $pathPrefix : ''; if (@is_dir($path)) { foreach (scandir($path) as $entry) { if (@is_file(($path . '/' . $entry))) { if ( ((string)$extensionList === ',,' || stripos($extensionList, ',' . pathinfo($entry, PATHINFO_EXTENSION) . ',') !== FALSE) && ((string)$excludePattern === '' || !preg_match(('/^' . $excludePattern . '$/'), $entry)) ) { if ($order === 'mtime') { $files[$entry] = filemtime($path . '/' . $entry); } else { $files[] = $entry; } } } } } else { return 'error opening path: "' . $path . '"'; } if ($order !== 'mtime') { foreach ($files as $key => $entry) { // Don't change this ever - extensions may depend on the fact that the hash is an md5 of the path! (import/export extension) $files[md5($pathPrefix . $entry)] = $valuePathPrefix . $entry; unset($files[$key]); } } else { asort($files); foreach ($files as $key => $entry) { // Don't change this ever - extensions may depend on the fact that the hash is an md5 of the path! (import/export extension) $files[md5($pathPrefix . $key)] = $valuePathPrefix . $key; unset($files[$key]); } } return $files; } $descriptions['version4'] = 'scandir, DirectoryIterator'; function version4($path, $extensionList = '', $prependPath = FALSE, $order = '', $excludePattern = '', $md5Index = FALSE) { $extensionList = ',' . $extensionList . ','; $files = array(); $path = rtrim($path, '/'); $pathPrefix = $path . '/'; $valuePathPrefix = $prependPath ? $pathPrefix : ''; if (@is_dir($path)) { $iterator = new DirectoryIterator($path); foreach ($iterator as $fileinfo) { if ($fileinfo->isFile()) { $fileName = $fileinfo->getFilename(); if ( ((string)$extensionList === ',,' || stripos($extensionList, ',' . pathinfo($fileName, PATHINFO_EXTENSION) . ',') !== FALSE) && ((string)$excludePattern === '' || !preg_match(('/^' . $excludePattern . '$/'), $fileName)) ) { if ($order === 'mtime') { $files[$fileName] = $fileinfo->getMTime(); } else { $files[] = $fileName; } } } } } else { return 'error opening path: "' . $path . '"'; } if ($order !== 'mtime') { foreach ($files as $key => $entry) { // Don't change this ever - extensions may depend on the fact that the hash is an md5 of the path! (import/export extension) $files[md5($pathPrefix . $entry)] = $valuePathPrefix . $entry; unset($files[$key]); } } else { asort($files); foreach ($files as $key => $entry) { // Don't change this ever - extensions may depend on the fact that the hash is an md5 of the path! (import/export extension) $files[md5($pathPrefix . $key)] = $valuePathPrefix . $key; unset($files[$key]); } } return $files; } $descriptions['version5'] = 'Glob'; function version5($path, $extensionList = '', $prependPath = FALSE, $order = '', $excludePattern = '', $md5Index = FALSE) { $extensionList = ($extensionList) ? $extensionList : '*'; $path = rtrim($path, '/'); $fileArray = array(); if (@is_dir($path)) { // Conversion to case insensitive character groups: // pdf,jpg,gif => [pP][dD][fF],[jJ][pP][gG],[gG][iI][fF] $extensionList = strtolower($extensionList); $caseInsensitiveExt = ''; foreach(str_split($extensionList) as $character) { if ($character !== '*' && $character !== ',') { $caseInsensitiveExt .= '[' . $character . strtoupper($character) . ']'; } else { $caseInsensitiveExt .= $character; } } // Fetch the entries $entries = glob("$path/*.{" . $caseInsensitiveExt . "}", GLOB_BRACE | GLOB_NOSORT); // Exclude unwanted entries if ($excludePattern) { $entries = array_filter( $entries, create_function('$a','return !preg_match("/^' . $excludePattern . '$/", $a);') ); } // If a file is found, add it to the fileArray with a md5 index if ($order == 'mtime') { $sortArray = array(); foreach ($entries as $entry) { if (@is_file($entry)) { // Don't change this ever - extensions may depend on the fact that // the hash is an md5 of the path! (import/export extension) $key = md5($entry); $sortArray[$key] = filemtime($entry); $fileArray[$key] = $prependPath ? $entry : basename($entry); } } asort($sortArray); $sortedFileArray = array(); foreach (array_keys($sortArray) as $key) { $sortedFileArray[$key] = $fileArray[$key]; } $fileArray = $sortedFileArray; } else { foreach ($entries as $entry) { if (@is_file($entry)) { // Don't change this ever - extensions may depend on the fact that // the hash is an md5 of the path! (import/export extension) $fileArray[md5($entry)] = $prependPath ? $entry : basename($entry); } } if ($order) { asort($fileArray); } } } return $fileArray; } /***************************************************************************** * Helper Methods: * * Add any methods that are needed by any of the test methods here. ****************************************************************************/ function inList($list, $item) { return strpos(',' . $list . ',', ',' . $item . ',') !== FALSE; } /***************************************************************************** * System (look, but don't touch ;-) . . . only touch if you must. ****************************************************************************/ $v = '1.0.0'; $reverseExecutionOrder = 0; if (isset($_GET['source']) && $_GET['source']) { show_source(__FILE__); exit; } if (isset($_GET['runs'])) $runs = preg_replace('/[^0-9]/', '', $_GET['runs']); if (isset($_GET['reverseExecutionOrder'])) $reverseExecutionOrder = intval($_GET['reverseExecutionOrder']); // Prepare $baselineTimes = $functionsToCall = $times = array(); $allFunctions = get_defined_functions(); $functions = array_filter($allFunctions['user'], create_function('$a','return strpos($a, "version") === 0;')); if ($reverseExecutionOrder) arsort($functions); foreach ($functions as $function) { $xAxis[] = $function; $functionsToCall[$function] = new ReflectionFunction($function); } // Execute foreach ($parameterSets as $setName => $parameters) { if (in_array($setName, $skipSets)) continue; // Description is used later on, so clone the parameters $functionParameters = $parameters; unset($functionParameters['description']); for ($i = 0; $i < $runs; $i++) { foreach ($functions as $function) { $start = microtime(TRUE); $result = $functionsToCall[$function]->invokeArgs($functionParameters); $time = microtime(TRUE) - $start; if ($function === 'version1') { $baselineTimes[$setName] += $time * 1000; } if (is_array($result)) { $resultObjects[$setName][$function] = array_slice($result, 0, 20, TRUE); } else { $resultObjects[$setName][$function] = $result; } $times[$setName][$function] += $time * 1000; } } } function findFastestTimes($times) { $fastestTimes = array(); foreach ($times as $setName => $timeData) { foreach ($timeData as $functionName => $time) { if (isset($fastestTimes[$functionName])) { $fastestTimes['overall'][$functionName] += $time; $fastestTimes[$setName][$functionName] += $time; } else { $fastestTimes['overall'][$functionName] = $time; $fastestTimes[$setName][$functionName] = $time; } } } $fastestTimes = array_filter($fastestTimes, 'asort'); return $fastestTimes; } function findWinner($times) { $averagedTimes = array(); foreach ($times as $timeData) { foreach ($timeData as $functionName => $time) { $averagedTimes[$functionName] += $time; } } asort($averagedTimes); return $averagedTimes; } $averagedTimes = findWinner($times); $fastestTimes = findFastestTimes($times); /** * Format an integer as a time value * * @param integer $time The value to format * * @return string */ function printSeconds($time) { $prefix = ''; $suffix = 'μs'; if ($time < 0) { $time = abs($time); $prefix = '-'; } if ($time === 0) { $suffix = ''; } if ($time >= 1000) { $time = $time / 1000; $suffix = 'ms'; } if ($time >= 1000) { $time = $time / 1000; $suffix = ' s'; } if ($time >= 60 && $suffix === ' s') { $time = $time / 60; $suffix = 'min!'; } return $prefix . sprintf("%.2f {$suffix}", $time); } ?> <?php echo $testName ?> | Tiny TYPO3 Test Suite v<?php echo $v ?>

/>

Winner using averaged times over all sets: .

1) { echo ''; } ?>

The fastest function in any set is .

1) { echo ''; } ?>

Parameter Sets

$functionData) { echo '

' , ucfirst($setName) , '

', '

' , $parameterSets[$setName]['description'] , '

', '

Parameters

'; } ?>

Data results

$functionData) { echo '

' . ucfirst($setName) . '

'; echo '

' . $parameterSets[$setName]['description'] . '

'; echo ''; foreach ($functionData as $function => $time) { echo '

', ucfirst($function), '

', '

', $descriptions[$function], '

'; var_dump($resultObjects[$setName][$function]); } } ?>

About

Tiny TYPO3 Test Suite v is a script that helps you test different method implementations. Get the latest version from github: https://github.com/Tuurlijk/TinyTypo3TestSuite

Help

Execution Order

In some cases, the second function (non baseline) always runs faster than the baseline. Even when switching the code around. This toggle enables you to reverse the running order to check for this behaviour. Your winning function should still win whatever the execution order. If that is not the case, then this test has failed to determine what code runs faster.

Source Code

Show the sourcecode of this file.
^ top Fork me on GitHub