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();