I'm trying to pack my web application (Symfony 2 project) with Phar. I've successfully packed Silex, a micro framework with hundred of files in a reasonable time (1-2 minutes).
The problem is on my development machine (i7 4770k, 16GB, SSD Raid 0, project on a RAM disk) creating the archive is really slow, it takes ~1 sec for each file. I really need to find out a way to speed up things.
Single iteration of reading/loading the file is slow. I'm adding files using:
function addFile(Phar $phar, SplFileInfo $file) { $root = realpath(__DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR); $path = strtr(str_replace($root, '', $file->getRealPath()), '\\', '/'); $phar->addFromString($path, file_get_contents($file)); } $phar = new Phar(/* ... */); $phar->startBuffering(); // ... foreach ($files as $file) { addFile($phar, $file); } // ... $phar->setStub(/* ... */); $phar->stopBuffering();
How can I speed up reading/adding files? Could be my OS (Windows) the problem?
EDIT: disabling buffering didn't solve the problem. Same speed adding from strings:
// This is VERY fast (~ 1 sec to read all 3000+ files) $strings = array(); foreach ($files as $file) { $root = realpath(__DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR); $path = strtr(str_replace($root, '', $file->getRealPath()), '\\', '/'); $strings[$path] = file_get_contents($file->getRealPath()); } // This is SLOW foreach ($strings as $local => $content) { $phar->addFromString($local, $content); }
EDIT: full quick&dirty script (may help) app/build
:
#!/usr/bin/env php <?php set_time_limit(0); require __DIR__.'/../vendor/autoload.php'; use Symfony\Component\Finder\Finder; use Symfony\Component\Console\Input\ArgvInput; $input = new ArgvInput(); $env = $input->getParameterOption(array('--env', '-e'), 'dev'); function addFile(Phar $phar, SplFileInfo $file) { $root = realpath(__DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR); $path = strtr(str_replace($root, '', $file->getRealPath()), '\\', '/'); $phar->addFromString($path, file_get_contents($file)); } $phar = new Phar(__DIR__ . "/../symfony.phar", 0, "symfony.phar"); $phar->startBuffering(); $envexclude = array_diff(array('dev', 'prod', 'test'), array($env)); // App $app = (new Finder()) ->files() ->notPath('/cache/') ->notPath('/logs/') ->notName('build') ->notname('/._('.implode('|', $envexclude).')\.yml$/') ->in(__DIR__); // Vendor $vendor = (new Finder()) ->files() ->ignoreVCS(true) ->name('*.{php,twig,xlf,xsd,xml}') ->notPath('/tests/i') ->notPath('/docs/i') ->in(__DIR__.'/../vendor'); // Src $src = (new Finder()) ->files() ->notPath('/tests/i') ->in(__DIR__.'/../src'); // Web $web = (new Finder()) ->files() ->in(__DIR__.'/../web') ->notname('/._('.implode('|', $envexclude).')\.php$/'); $all = array_merge( iterator_to_array($app), iterator_to_array($src), iterator_to_array($vendor), iterator_to_array($web) ); $c = count($all); $i = 1; $strings = array(); foreach ($all as $file) { addFile($phar, $file); echo "Done $i/$c\r\n"; $i++; } $stub = <<<'STUB' Phar::webPhar(null, "/web/app_phar.php", null, array(), function ($path) { return '/web/app_phar.php'.$path; }); __HALT_COMPILER(); STUB; $phar->setStub($stub); $phar->stopBuffering();
Try using Phar::addFile($file) instead of Phar::addFromString(file_get_contents($file))
i.e.
function addFile(Phar $phar, SplFileInfo $file) { $root = realpath(__DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR); $path = strtr(str_replace($root, '', $file->getRealPath()), '\\', '/'); //$phar->addFromString($path, file_get_contents($file)); $phar->addFile($file,$path); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With