<?php class GitPHP_Log { // ... public function timerStart() { array_push($this->timers, microtime(true)); } public function timerStop($name, $value = null) { $timer = array_pop($this->timers); $duration = microtime(true) - $timer; // , foreach ($this->timers as &$item) $item += $duration; $this->Log($name, $value, $duration); } // ... }
timerStart()
is called, at the end - timerStop()
with the name of the timer and optional additional data: <?php $Log = new GitPHP_Log; $Log->timerStart(); $result = 0; $mult = 4; for ($i = 1; $i < 1000000; $i+=2) { $result += $mult / $i; $mult = -$mult; } $Log->timerStop("PI computation", $result);
<?php class GitPHP_DebugAutoLog { private $name; public function __construct($name) { $this->name = $name; GitPHP_Log::GetInstance()->timerStart(); } public function __destruct() { GitPHP_Log::GetInstance()->timerStop($this->name); } }
$Log = new GitPHP_DebugAutoLog('timer_name');
the time of its execution will be automatically measured at the beginning of any function or method, and when exiting the function: <?php function doSomething($a) { $Log = GitPHP_DebugAutoLog('doSomething'); if ($a > 5) { echo "Hello world!\n"; sleep(5); return; } sleep(1); }
git cat-file -t
only to find out the type of commit and whether this commit is a “lightweight tag” ( http://git-scm.com/book/en/Git-Basics -Tagging # Lightweight-Tags ). Lightweight tags in Git is a type of tag that is created by default and contains a link to a specific commit. Since no other tag types were present in our repository, we simply removed this check and saved a couple of thousand git cat-file -t,
calls git cat-file -t,
took about 20 seconds.GitPHP_TagList
class has a method that is responsible for getting a list of tags that reference the specified commit: <?php class GitPHP_TagList extends GitPHP_RefList { // ... public function GetCommitTags($commit) { if (!$commit) return array(); $commitHash = $commit->GetHash(); if (!$this->dataLoaded) $this->LoadData(); $tags = array(); foreach ($this->refs as $tag => $hash) { if (isset($this->commits[$tag])) { // ... } else { $tagObj = $this->project->GetObjectManager()->GetTag($tag, $hash); $tagCommitHash = $tagObj->GetCommitHash(); // ... if ($tagCommitHash == $commitHash) { $tags[] = $tagObj; } } } return $tags; } // ... }
array( commit_hash => array(tags) )
, you need to pay attention to the GetCommitHash()
method: it calls the Load($tag)
method, which, when implemented using an external Git utility, does the following: <?php class GitPHP_TagLoad_Git implements GitPHP_TagLoadStrategy_Interface { // ... public function Load($tag) { // ... $args[] = '-t'; $args[] = $tag->GetHash(); $ret = trim($this->exe->Execute($tag->GetProject()->GetPath(), GIT_CAT_FILE, $args)); if ($ret === 'commit') { // ... return array(/* ... */); } // ... $ret = $this->exe->Execute($tag->GetProject()->GetPath(), GIT_CAT_FILE, $args); // ... return array(/* ... */); } }
<?php class GitPHP_CommitLoad_Git extends GitPHP_CommitLoad_Base { public function Load($commit) { // ... /* get data from git_rev_list */ $args = array(); $args[] = '--header'; $args[] = '--parents'; $args[] = '--max-count=1'; $args[] = '--abbrev-commit'; $args[] = $commit->GetHash(); $ret = $this->exe->Execute($commit->GetProject()->GetPath(), GIT_REV_LIST, $args); // ... return array( // ... ); } // ... }
git cat-file --batch
and load all the results at once. <?php class GitPHP_Project { // ... public function BatchReadData(array $hashes) { if (!count($hashes)) return array(); $outfile = tempnam('/tmp', 'objlist'); $hashlistfile = tempnam('/tmp', 'objlist'); file_put_contents($hashlistfile, implode("\n", $hashes)); $Git = new GitPHP_GitExe($this); $Git->Execute(GIT_CAT_FILE, array('--batch', ' < ' . escapeshellarg($hashlistfile), ' > ' . escapeshellarg($outfile))); unlink($hashlistfile); $fp = fopen($outfile, 'r'); unlink($outfile); $types = $contents = array(); while (!feof($fp)) { $ln = rtrim(fgets($fp)); if (!$ln) continue; list($hash, $type, $n) = explode(" ", rtrim($ln)); $contents[$hash] = fread($fp, $n); $types[$hash] = $type; } return array('contents' => $contents, 'types' => $types); } // ... }
git cat-file --batch
). This optimization reduced the average page load time from more than 20 seconds to 0.5 seconds. So we solved the problem of slow GitPHP in our project.git cat-file --batch
. Although not documented, this command allows you to download information one commit at a time, without losing performance! During operation, one line is read from the standard input and the results are sent to the standard output without buffering. This means that we can open git cat-file --batch
via proc_open()
and get the results immediately, without reworking the architecture! <?php // ... class GitPHP_GitExe implements GitPHP_Observable_Interface { // ... public function GetObjectData($projectPath, $hash) { $process = $this->GetProcess($projectPath); $pipes = $process['pipes']; $data = $hash . "\n"; fwrite($pipes[0], $data); fflush($pipes[0]); $ln = rtrim(fgets($pipes[1])); $parts = explode(" ", rtrim($ln)); list($hash, $type, $n) = $parts; $contents = ''; while (strlen($contents) < $n) { $buf = fread($pipes[1], min(4096, $n - strlen($contents))); $contents .= $buf; } return array( 'contents' => $contents, 'type' => $type, ); } // ... }
git cat-file
and git rev-list
calls to a call to our optimized function.$compat = false;
in the configuration.Source: https://habr.com/ru/post/200946/
All Articles