mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-18 11:30:55 +01:00
Record lock timing information on PushEvents
Summary: Depends on D19249. Ref T13109. Add timing information to the `PushEvent`: - `writeWait`: Time spent waiting for a write lock. - `readWait`: Time spent waiting for a read lock. - `hostWait`: Roughly, total time spent on the leaf node. The primary goal here is to see if `readWait` is meaningful in the wild. If it is, that motivates smarter routing, and the value of smarter routing can be demonstrated by looking for a reduction in read wait times. Test Plan: Pushed some stuff, saw reasonable timing values in the table. Saw timing information in "Export Data". Maniphest Tasks: T13109 Differential Revision: https://secure.phabricator.com/D19250
This commit is contained in:
parent
69bff489d4
commit
df3c937dab
7 changed files with 111 additions and 17 deletions
8
resources/sql/autopatches/20180322.lock.02.wait.sql
Normal file
8
resources/sql/autopatches/20180322.lock.02.wait.sql
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
ALTER TABLE {$NAMESPACE}_repository.repository_pushevent
|
||||||
|
ADD writeWait BIGINT UNSIGNED;
|
||||||
|
|
||||||
|
ALTER TABLE {$NAMESPACE}_repository.repository_pushevent
|
||||||
|
ADD readWait BIGINT UNSIGNED;
|
||||||
|
|
||||||
|
ALTER TABLE {$NAMESPACE}_repository.repository_pushevent
|
||||||
|
ADD hostWait BIGINT UNSIGNED;
|
|
@ -315,12 +315,15 @@ final class DiffusionRepositoryClusterEngine extends Phobject {
|
||||||
|
|
||||||
$lock_wait = phutil_units('2 minutes in seconds');
|
$lock_wait = phutil_units('2 minutes in seconds');
|
||||||
try {
|
try {
|
||||||
|
$write_wait_start = microtime(true);
|
||||||
|
|
||||||
$start = PhabricatorTime::getNow();
|
$start = PhabricatorTime::getNow();
|
||||||
$step_wait = 1;
|
$step_wait = 1;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
$write_lock->lock((int)floor($step_wait));
|
$write_lock->lock((int)floor($step_wait));
|
||||||
|
$write_wait_end = microtime(true);
|
||||||
break;
|
break;
|
||||||
} catch (PhutilLockException $ex) {
|
} catch (PhutilLockException $ex) {
|
||||||
$waited = (PhabricatorTime::getNow() - $start);
|
$waited = (PhabricatorTime::getNow() - $start);
|
||||||
|
@ -370,12 +373,14 @@ final class DiffusionRepositoryClusterEngine extends Phobject {
|
||||||
'documentation for instructions.'));
|
'documentation for instructions.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$read_wait_start = microtime(true);
|
||||||
try {
|
try {
|
||||||
$max_version = $this->synchronizeWorkingCopyBeforeRead();
|
$max_version = $this->synchronizeWorkingCopyBeforeRead();
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
$write_lock->unlock();
|
$write_lock->unlock();
|
||||||
throw $ex;
|
throw $ex;
|
||||||
}
|
}
|
||||||
|
$read_wait_end = microtime(true);
|
||||||
|
|
||||||
$pid = getmypid();
|
$pid = getmypid();
|
||||||
$hash = Filesystem::readRandomCharacters(12);
|
$hash = Filesystem::readRandomCharacters(12);
|
||||||
|
@ -394,6 +399,15 @@ final class DiffusionRepositoryClusterEngine extends Phobject {
|
||||||
|
|
||||||
$this->clusterWriteVersion = $max_version;
|
$this->clusterWriteVersion = $max_version;
|
||||||
$this->clusterWriteLock = $write_lock;
|
$this->clusterWriteLock = $write_lock;
|
||||||
|
|
||||||
|
$write_wait = ($write_wait_end - $write_wait_start);
|
||||||
|
$read_wait = ($read_wait_end - $read_wait_start);
|
||||||
|
|
||||||
|
$log = $this->logger;
|
||||||
|
if ($log) {
|
||||||
|
$log->writeClusterEngineLogProperty('readWait', $read_wait);
|
||||||
|
$log->writeClusterEngineLogProperty('writeWait', $write_wait);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,5 +3,6 @@
|
||||||
interface DiffusionRepositoryClusterEngineLogInterface {
|
interface DiffusionRepositoryClusterEngineLogInterface {
|
||||||
|
|
||||||
public function writeClusterEngineLogMessage($message);
|
public function writeClusterEngineLogMessage($message);
|
||||||
|
public function writeClusterEngineLogProperty($key, $value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@ final class DiffusionGitReceivePackSSHWorkflow extends DiffusionGitSSHWorkflow {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function executeRepositoryOperations() {
|
protected function executeRepositoryOperations() {
|
||||||
|
$host_wait_start = microtime(true);
|
||||||
|
|
||||||
$repository = $this->getRepository();
|
$repository = $this->getRepository();
|
||||||
$viewer = $this->getSSHUser();
|
$viewer = $this->getSSHUser();
|
||||||
$device = AlmanacKeys::getLiveDevice();
|
$device = AlmanacKeys::getLiveDevice();
|
||||||
|
@ -71,6 +73,14 @@ final class DiffusionGitReceivePackSSHWorkflow extends DiffusionGitSSHWorkflow {
|
||||||
PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE,
|
PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE,
|
||||||
PhabricatorRepositoryStatusMessage::CODE_OKAY);
|
PhabricatorRepositoryStatusMessage::CODE_OKAY);
|
||||||
$this->waitForGitClient();
|
$this->waitForGitClient();
|
||||||
|
|
||||||
|
$host_wait_end = microtime(true);
|
||||||
|
|
||||||
|
$this->updatePushLogWithTimingInformation(
|
||||||
|
$this->getClusterEngineLogProperty('writeWait'),
|
||||||
|
$this->getClusterEngineLogProperty('readWait'),
|
||||||
|
($host_wait_end - $host_wait_start));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $err;
|
return $err;
|
||||||
|
@ -89,4 +99,37 @@ final class DiffusionGitReceivePackSSHWorkflow extends DiffusionGitSSHWorkflow {
|
||||||
->execute();
|
->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function updatePushLogWithTimingInformation(
|
||||||
|
$write_wait,
|
||||||
|
$read_wait,
|
||||||
|
$host_wait) {
|
||||||
|
|
||||||
|
if ($write_wait !== null) {
|
||||||
|
$write_wait = (int)(1000000 * $write_wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($read_wait !== null) {
|
||||||
|
$read_wait = (int)(1000000 * $read_wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($host_wait !== null) {
|
||||||
|
$host_wait = (int)(1000000 * $host_wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
$identifier = $this->getRequestIdentifier();
|
||||||
|
|
||||||
|
$event = new PhabricatorRepositoryPushEvent();
|
||||||
|
$conn = $event->establishConnection('w');
|
||||||
|
|
||||||
|
queryfx(
|
||||||
|
$conn,
|
||||||
|
'UPDATE %T SET writeWait = %nd, readWait = %nd, hostWait = %nd
|
||||||
|
WHERE requestIdentifier = %s',
|
||||||
|
$event->getTableName(),
|
||||||
|
$write_wait,
|
||||||
|
$read_wait,
|
||||||
|
$host_wait,
|
||||||
|
$identifier);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ abstract class DiffusionGitSSHWorkflow
|
||||||
extends DiffusionSSHWorkflow
|
extends DiffusionSSHWorkflow
|
||||||
implements DiffusionRepositoryClusterEngineLogInterface {
|
implements DiffusionRepositoryClusterEngineLogInterface {
|
||||||
|
|
||||||
|
private $engineLogProperties = array();
|
||||||
|
|
||||||
protected function writeError($message) {
|
protected function writeError($message) {
|
||||||
// Git assumes we'll add our own newlines.
|
// Git assumes we'll add our own newlines.
|
||||||
return parent::writeError($message."\n");
|
return parent::writeError($message."\n");
|
||||||
|
@ -14,6 +16,14 @@ abstract class DiffusionGitSSHWorkflow
|
||||||
$this->getErrorChannel()->update();
|
$this->getErrorChannel()->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function writeClusterEngineLogProperty($key, $value) {
|
||||||
|
$this->engineLogProperties[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getClusterEngineLogProperty($key, $default = null) {
|
||||||
|
return idx($this->engineLogProperties, $key, $default);
|
||||||
|
}
|
||||||
|
|
||||||
protected function identifyRepository() {
|
protected function identifyRepository() {
|
||||||
$args = $this->getArgs();
|
$args = $this->getArgs();
|
||||||
$path = head($args->getArg('dir'));
|
$path = head($args->getArg('dir'));
|
||||||
|
|
|
@ -98,57 +98,66 @@ final class PhabricatorRepositoryPushLogSearchEngine
|
||||||
$viewer = $this->requireViewer();
|
$viewer = $this->requireViewer();
|
||||||
|
|
||||||
$fields = array(
|
$fields = array(
|
||||||
$fields[] = id(new PhabricatorIDExportField())
|
id(new PhabricatorIDExportField())
|
||||||
->setKey('pushID')
|
->setKey('pushID')
|
||||||
->setLabel(pht('Push ID')),
|
->setLabel(pht('Push ID')),
|
||||||
$fields[] = id(new PhabricatorStringExportField())
|
id(new PhabricatorStringExportField())
|
||||||
->setKey('unique')
|
->setKey('unique')
|
||||||
->setLabel(pht('Unique')),
|
->setLabel(pht('Unique')),
|
||||||
$fields[] = id(new PhabricatorStringExportField())
|
id(new PhabricatorStringExportField())
|
||||||
->setKey('protocol')
|
->setKey('protocol')
|
||||||
->setLabel(pht('Protocol')),
|
->setLabel(pht('Protocol')),
|
||||||
$fields[] = id(new PhabricatorPHIDExportField())
|
id(new PhabricatorPHIDExportField())
|
||||||
->setKey('repositoryPHID')
|
->setKey('repositoryPHID')
|
||||||
->setLabel(pht('Repository PHID')),
|
->setLabel(pht('Repository PHID')),
|
||||||
$fields[] = id(new PhabricatorStringExportField())
|
id(new PhabricatorStringExportField())
|
||||||
->setKey('repository')
|
->setKey('repository')
|
||||||
->setLabel(pht('Repository')),
|
->setLabel(pht('Repository')),
|
||||||
$fields[] = id(new PhabricatorPHIDExportField())
|
id(new PhabricatorPHIDExportField())
|
||||||
->setKey('pusherPHID')
|
->setKey('pusherPHID')
|
||||||
->setLabel(pht('Pusher PHID')),
|
->setLabel(pht('Pusher PHID')),
|
||||||
$fields[] = id(new PhabricatorStringExportField())
|
id(new PhabricatorStringExportField())
|
||||||
->setKey('pusher')
|
->setKey('pusher')
|
||||||
->setLabel(pht('Pusher')),
|
->setLabel(pht('Pusher')),
|
||||||
$fields[] = id(new PhabricatorPHIDExportField())
|
id(new PhabricatorPHIDExportField())
|
||||||
->setKey('devicePHID')
|
->setKey('devicePHID')
|
||||||
->setLabel(pht('Device PHID')),
|
->setLabel(pht('Device PHID')),
|
||||||
$fields[] = id(new PhabricatorStringExportField())
|
id(new PhabricatorStringExportField())
|
||||||
->setKey('device')
|
->setKey('device')
|
||||||
->setLabel(pht('Device')),
|
->setLabel(pht('Device')),
|
||||||
$fields[] = id(new PhabricatorStringExportField())
|
id(new PhabricatorStringExportField())
|
||||||
->setKey('type')
|
->setKey('type')
|
||||||
->setLabel(pht('Ref Type')),
|
->setLabel(pht('Ref Type')),
|
||||||
$fields[] = id(new PhabricatorStringExportField())
|
id(new PhabricatorStringExportField())
|
||||||
->setKey('name')
|
->setKey('name')
|
||||||
->setLabel(pht('Ref Name')),
|
->setLabel(pht('Ref Name')),
|
||||||
$fields[] = id(new PhabricatorStringExportField())
|
id(new PhabricatorStringExportField())
|
||||||
->setKey('old')
|
->setKey('old')
|
||||||
->setLabel(pht('Ref Old')),
|
->setLabel(pht('Ref Old')),
|
||||||
$fields[] = id(new PhabricatorStringExportField())
|
id(new PhabricatorStringExportField())
|
||||||
->setKey('new')
|
->setKey('new')
|
||||||
->setLabel(pht('Ref New')),
|
->setLabel(pht('Ref New')),
|
||||||
$fields[] = id(new PhabricatorIntExportField())
|
id(new PhabricatorIntExportField())
|
||||||
->setKey('flags')
|
->setKey('flags')
|
||||||
->setLabel(pht('Flags')),
|
->setLabel(pht('Flags')),
|
||||||
$fields[] = id(new PhabricatorStringListExportField())
|
id(new PhabricatorStringListExportField())
|
||||||
->setKey('flagNames')
|
->setKey('flagNames')
|
||||||
->setLabel(pht('Flag Names')),
|
->setLabel(pht('Flag Names')),
|
||||||
$fields[] = id(new PhabricatorIntExportField())
|
id(new PhabricatorIntExportField())
|
||||||
->setKey('result')
|
->setKey('result')
|
||||||
->setLabel(pht('Result')),
|
->setLabel(pht('Result')),
|
||||||
$fields[] = id(new PhabricatorStringExportField())
|
id(new PhabricatorStringExportField())
|
||||||
->setKey('resultName')
|
->setKey('resultName')
|
||||||
->setLabel(pht('Result Name')),
|
->setLabel(pht('Result Name')),
|
||||||
|
id(new PhabricatorIntExportField())
|
||||||
|
->setKey('writeWait')
|
||||||
|
->setLabel(pht('Write Wait (us)')),
|
||||||
|
id(new PhabricatorIntExportField())
|
||||||
|
->setKey('readWait')
|
||||||
|
->setLabel(pht('Read Wait (us)')),
|
||||||
|
id(new PhabricatorIntExportField())
|
||||||
|
->setKey('hostWait')
|
||||||
|
->setLabel(pht('Host Wait (us)')),
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($viewer->getIsAdmin()) {
|
if ($viewer->getIsAdmin()) {
|
||||||
|
@ -228,6 +237,9 @@ final class PhabricatorRepositoryPushLogSearchEngine
|
||||||
'flagNames' => $flag_names,
|
'flagNames' => $flag_names,
|
||||||
'result' => $result,
|
'result' => $result,
|
||||||
'resultName' => $result_name,
|
'resultName' => $result_name,
|
||||||
|
'writeWait' => $event->getWriteWait(),
|
||||||
|
'readWait' => $event->getReadWait(),
|
||||||
|
'hostWait' => $event->getHostWait(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($viewer->getIsAdmin()) {
|
if ($viewer->getIsAdmin()) {
|
||||||
|
|
|
@ -16,6 +16,9 @@ final class PhabricatorRepositoryPushEvent
|
||||||
protected $remoteProtocol;
|
protected $remoteProtocol;
|
||||||
protected $rejectCode;
|
protected $rejectCode;
|
||||||
protected $rejectDetails;
|
protected $rejectDetails;
|
||||||
|
protected $writeWait;
|
||||||
|
protected $readWait;
|
||||||
|
protected $hostWait;
|
||||||
|
|
||||||
private $repository = self::ATTACHABLE;
|
private $repository = self::ATTACHABLE;
|
||||||
private $logs = self::ATTACHABLE;
|
private $logs = self::ATTACHABLE;
|
||||||
|
@ -35,6 +38,9 @@ final class PhabricatorRepositoryPushEvent
|
||||||
'remoteProtocol' => 'text32?',
|
'remoteProtocol' => 'text32?',
|
||||||
'rejectCode' => 'uint32',
|
'rejectCode' => 'uint32',
|
||||||
'rejectDetails' => 'text64?',
|
'rejectDetails' => 'text64?',
|
||||||
|
'writeWait' => 'uint64?',
|
||||||
|
'readWait' => 'uint64?',
|
||||||
|
'hostWait' => 'uint64?',
|
||||||
),
|
),
|
||||||
self::CONFIG_KEY_SCHEMA => array(
|
self::CONFIG_KEY_SCHEMA => array(
|
||||||
'key_repository' => array(
|
'key_repository' => array(
|
||||||
|
|
Loading…
Reference in a new issue