Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Phar creation slow on a powerful PC, how to speed up (loading/reading ~3000 files)?

Tags:

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(); 
like image 874
gremo Avatar asked May 30 '14 22:05

gremo


1 Answers

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); } 
like image 192
FuzzyTree Avatar answered Sep 19 '22 17:09

FuzzyTree