Skip to content

Commit

Permalink
Merge pull request #161 from TheHett/master
Browse files Browse the repository at this point in the history
Improve profiling
  • Loading branch information
Sammaye committed Nov 14, 2013
2 parents a66fde0 + ebb16a4 commit f0521ad
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 63 deletions.
48 changes: 40 additions & 8 deletions EMongoClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ class EMongoClient extends CApplicationComponent{

/**
* Are we using journaled writes here? Beware this makes all writes wait for the journal, it does not
* state whether MongoDB is using journaling. Note: this is NOT straight to disk,
* it infact makes the journal to disk time a third of its normal time (anywhere between 2-30ms).
* state whether MongoDB is using journaling. Note: this is NOT straight to disk,
* it infact makes the journal to disk time a third of its normal time (anywhere between 2-30ms).
* Only works 1.3+ driver
* @var boolean
*/
Expand All @@ -60,7 +60,7 @@ class EMongoClient extends CApplicationComponent{
* @var boolean
*/
public $setSlaveOkay = false;

/**
* Enables logging to the profiler
* @var boolean
Expand All @@ -87,7 +87,7 @@ class EMongoClient extends CApplicationComponent{
private $_meta = array();

/**
* The default action is to find a getX whereby X is the $k param
* The default action is to find a getX whereby X is the $k param
* you input. The secondary function, if not getter found, is to get a collection
*/
public function __get($k){
Expand Down Expand Up @@ -195,7 +195,7 @@ public function close(){
}

/**
* This function is designed to be a helper to make calling the aggregate command
* This function is designed to be a helper to make calling the aggregate command
* more standard across all drivers.
* @param string $collection
* @param $pipelines
Expand Down Expand Up @@ -231,7 +231,7 @@ public function selectCollection($name){

/**
* Sets the document cache for any particular document (EMongoDocument/EMongoModel)
* sent in as the first parameter of this function. Will not cache actual EMongoDocument/EMongoModel instances
* sent in as the first parameter of this function. Will not cache actual EMongoDocument/EMongoModel instances
* only active classes that inherit these
* @param $o
*/
Expand Down Expand Up @@ -277,10 +277,10 @@ function setDocumentCache($o){
public function getFieldCache($name, $include_virtual = false){
$doc = isset($this->_meta[$name]) ? $this->_meta[$name] : array();
$fields = array();

foreach($doc as $name => $opts)
if($include_virtual || !$opts['virtual']) $fields[] = $name;
return $fields;
return $fields;
}

/**
Expand Down Expand Up @@ -352,6 +352,38 @@ public function setReadPreference($pref, $options=array()){
public function setSlaveOkay($bool){
return $this->getConnection()->setSlaveOkay($bool);
}

/**
* @return array the first element indicates the number of query statements executed,
* and the second element the total time spent in query execution.
*/
public function getStats()
{
$logger=Yii::getLogger();
$timings=$logger->getProfilingResults(null,'extensions.MongoYii.EMongoDocument.findOne');
$count=count($timings);
$time=array_sum($timings);
$timings=$logger->getProfilingResults(null,'extensions.MongoYii.EMongoDocument.insert');
$count+=count($timings);
$time+=array_sum($timings);
$timings=$logger->getProfilingResults(null,'extensions.MongoYii.EMongoDocument.find');
$count+=count($timings);
$time+=array_sum($timings);
$timings=$logger->getProfilingResults(null,'extensions.MongoYii.EMongoDocument.deleteByPk');
$count+=count($timings);
$time+=array_sum($timings);
$timings=$logger->getProfilingResults(null,'extensions.MongoYii.EMongoDocument.updateByPk');
$count+=count($timings);
$time+=array_sum($timings);
$timings=$logger->getProfilingResults(null,'extensions.MongoYii.EMongoDocument.updateAll');
$count+=count($timings);
$time+=array_sum($timings);
$timings=$logger->getProfilingResults(null,'extensions.MongoYii.EMongoDocument.deleteAll');
$count+=count($timings);
$time+=array_sum($timings);

return array($count,$time);
}
}

/**
Expand Down
138 changes: 83 additions & 55 deletions EMongoDocument.php
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ public function insert($attributes = null){
if($this->beforeSave())
{
$this->trace(__FUNCTION__);

if($attributes!==null)
$document=$this->filterRawDocument($this->getAttributes($attributes));
else
Expand All @@ -595,12 +595,15 @@ public function insert($attributes = null){
if(YII_DEBUG){
// we're actually physically testing for Yii debug mode here to stop us from
// having to do the serialisation on the update doc normally.
Yii::trace('Executing insert: {$document:'.json_encode($document).'}', 'extensions.MongoYii.EMongoDocument');
}
Yii::trace('Executing insert: {$document:'.json_encode($document).'}', 'extensions.MongoYii.EMongoDocument');
}
if($this->getDbConnection()->enableProfiling)
Yii::beginProfile('extensions.MongoYii.EMongoDocument.query.'.$this->collectionName().'.insert('.'{$document:'.json_encode($document).'})', 'extensions.MongoYii.EMongoDocument.insert');
$this->lastError = $this->getCollection()->insert($document, $this->getDbConnection()->getDefaultWriteConcern());
if($this->getDbConnection()->enableProfiling)
$this->profile('extensions.MongoYii.EMongoDocument.insert('.'{$document:'.json_encode($document).'})', 'extensions.MongoYii.EMongoDocument.insert');
if($this->lastError = $this->getCollection()->insert($document, $this->getDbConnection()->getDefaultWriteConcern())){
Yii::endProfile('extensions.MongoYii.EMongoDocument.query.'.$this->collectionName().'.insert('.'{$document:'.json_encode($document).'})', 'extensions.MongoYii.EMongoDocument.insert');

if($this->lastError){
$this->afterSave();
$this->setIsNewRecord(false);
$this->setScenario('update');
Expand Down Expand Up @@ -638,9 +641,9 @@ public function update($attributes=null){
$attributes = $this->getRawDocument();
if(isset($attributes['_id']))
unset($attributes['_id']); // Unset the _id before update

if($this->versioned()){

$version=$this->{$this->versionField()};
$attributes[$this->versionField()]=$this->{$this->versionField()}=$this->{$this->versionField()}>0?$this->{$this->versionField()}+1:1;

Expand Down Expand Up @@ -743,10 +746,17 @@ public function findOne($criteria = array(), $fields = array()){
Yii::trace('Executing findOne: '.'{$query:'.json_encode($query).',$project:'.json_encode($project).'}','extensions.MongoYii.EMongoDocument');

if($this->getDbConnection()->enableProfiling)
$this->profile('extensions.MongoYii.EMongoDocument.findOne('.'{$query:'.json_encode($query).',$project:'.json_encode($project).'}'.')',
'extensions.MongoYii.EMongoDocument.findOne');
Yii::beginProfile('extensions.MongoYii.EMongoDocument.query.'.$this->collectionName().'.findOne('.'{$query:'.json_encode($query).',$project:'.json_encode($project).'}'.')',
'extensions.MongoYii.EMongoDocument.findOne');

if(($record=$this->getCollection()->findOne($query,$project)) !== null){
$record=$this->getCollection()->findOne($query,$project);

if($this->getDbConnection()->enableProfiling)
Yii::endProfile('extensions.MongoYii.EMongoDocument.query.'.$this->collectionName().'.findOne('.'{$query:'.json_encode($query).',$project:'.json_encode($project).'}'.')',
'extensions.MongoYii.EMongoDocument.findOne');


if($record !== null){
$this->resetScope();
return $this->populateRecord($record, true, $project === array() ? false : true);
}
Expand Down Expand Up @@ -790,9 +800,9 @@ public function findAllByPk($pk, $fields = array()){
*/
public function find($criteria = array(), $fields = array()){
$this->trace(__FUNCTION__);

$this->beforeFind(); // Apparently this is applied before even scopes...

if($criteria instanceof EMongoCriteria){
$c = $criteria->mergeWith($this->getDbCriteria())->toArray();
$criteria = array();
Expand All @@ -804,30 +814,35 @@ public function find($criteria = array(), $fields = array()){
$project=$this->mergeCriteria(isset($c['project']) ? $c['project'] : array(), $fields);

Yii::trace('Executing find: '.
'{$query:'.json_encode($query)
.',$project:'.json_encode($project)
.(isset($c['sort']) ? ',$sort:'.json_encode($c['sort']).',' : '')
.(isset($c['skip']) ? ',$skip:'.json_encode($c['skip']).',' : '')
.(isset($c['limit']) ? ',$limit:'.json_encode($c['limit']).',' : '')
.'}','extensions.MongoYii.EMongoDocument');
if($this->getDbConnection()->enableProfiling)
$this->profile('extensions.MongoYii.EMongoDocument.find('.'{$query:'.json_encode($query)
'{$query:'.json_encode($query)
.',$project:'.json_encode($project)
.(isset($c['sort']) ? ',$sort:'.json_encode($c['sort']).',' : '')
.(isset($c['skip']) ? ',$skip:'.json_encode($c['skip']).',' : '')
.(isset($c['limit']) ? ',$limit:'.json_encode($c['limit']).',' : '')
.'}','extensions.MongoYii.EMongoDocument');
if($this->getDbConnection()->enableProfiling) {
$token = 'extensions.MongoYii.EMongoDocument.query.'.$this->collectionName().'.find('.'{$query:'.json_encode($query)
.',$project:'.json_encode($project)
.(isset($c['sort']) ? ',$sort:'.json_encode($c['sort']).',' : '')
.(isset($c['skip']) ? ',$skip:'.json_encode($c['skip']).',' : '')
.(isset($c['limit']) ? ',$limit:'.json_encode($c['limit']).',' : '')
.'})', 'extensions.MongoYii.EMongoDocument.find');
.'})';
Yii::beginProfile($token, 'extensions.MongoYii.EMongoDocument.find');
}

if($c !== array()){
$cursor = new EMongoCursor($this, $query, $project);
if(isset($c['sort'])) $cursor->sort($c['sort']);
if(isset($c['skip'])) $cursor->skip($c['skip']);
if(isset($c['limit'])) $cursor->limit($c['limit']);

$this->resetScope();
return $cursor;
} else {
$cursor = new EMongoCursor($this, $criteria, $project);
}
return new EMongoCursor($this, $criteria, $project);
if($this->getDbConnection()->enableProfiling)
Yii::endProfile($token, 'extensions.MongoYii.EMongoDocument.find');

return $cursor;
}

/**
Expand Down Expand Up @@ -870,11 +885,14 @@ public function deleteByPk($pk, $criteria = array(), $options = array()){
$query=array_merge(array($this->primaryKey() => $pk), $criteria);

Yii::trace('Executing deleteByPk: '.'{$query:'.json_encode($query).'}','extensions.MongoYii.EMongoDocument');


if($this->getDbConnection()->enableProfiling)
Yii::beginProfile('extensions.MongoYii.EMongoDocument.query.'.$this->collectionName().'.deleteByPk('.'{$query:'.json_encode($query).'}'.')' ,'extensions.MongoYii.EMongoDocument.deleteByPk');
$result = $this->getCollection()->remove($query, array_merge($this->getDbConnection()->getDefaultWriteConcern(), $options));
if($this->getDbConnection()->enableProfiling)
$this->profile('extensions.MongoYii.EMongoDocument.deleteByPk('.'{$query:'.json_encode($query).'}'.')' ,'extensions.MongoYii.EMongoDocument.deleteByPk');
return $this->getCollection()->remove($query, array_merge($this->getDbConnection()->getDefaultWriteConcern(), $options));
Yii::endProfile('extensions.MongoYii.EMongoDocument.query.'.$this->collectionName().'.deleteByPk('.'{$query:'.json_encode($query).'}'.')' ,'extensions.MongoYii.EMongoDocument.deleteByPk');

return $result;
}

/**
Expand All @@ -897,14 +915,20 @@ public function updateByPk($pk, $updateDoc = array(), $criteria = array(), $opti
if(YII_DEBUG){
// we're actually physically testing for Yii debug mode here to stop us from
// having to do the serialisation on the update doc normally.
Yii::trace('Executing updateByPk: '.'{$query:'.json_encode($query).',$document:'.json_encode($updateDoc).'}','extensions.MongoYii.EMongoDocument');
Yii::trace('Executing updateByPk: '.'{$query:'.json_encode($query).',$document:'.json_encode($updateDoc).'}','extensions.MongoYii.EMongoDocument');
}
if($this->getDbConnection()->enableProfiling)
$this->profile('extensions.MongoYii.EMongoDocument.updateByPk('.'{$query:'.json_encode($query).',$document:'.json_encode($updateDoc).'}'.')',
'extensions.MongoYii.EMongoDocument.updateByPk');
Yii::beginProfile('extensions.MongoYii.EMongoDocument.query.'.$this->collectionName().'.updateByPk('.'{$query:'.json_encode($query).',$document:'.json_encode($updateDoc).'}'.')',
'extensions.MongoYii.EMongoDocument.updateByPk');

$result = $this->getCollection()->update($query, $updateDoc,
array_merge($this->getDbConnection()->getDefaultWriteConcern(), $options));

if($this->getDbConnection()->enableProfiling)
Yii::endProfile('extensions.MongoYii.EMongoDocument.query.'.$this->collectionName().'.updateByPk('.'{$query:'.json_encode($query).',$document:'.json_encode($updateDoc).'}'.')',
'extensions.MongoYii.EMongoDocument.updateByPk');

return $this->getCollection()->update($query, $updateDoc,
array_merge($this->getDbConnection()->getDefaultWriteConcern(), $options));
return $result;
}

/**
Expand All @@ -927,14 +951,22 @@ public function updateAll($criteria = array(), $updateDoc = array(), $options =
Yii::trace('Executing updateAll: '.
'{$query:'.json_encode($criteria)
.',$document:'.json_encode($updateDoc)
.',$options:'.json_encode($options).'}','extensions.MongoYii.EMongoDocument');
.',$options:'.json_encode($options).'}','extensions.MongoYii.EMongoDocument');
}
if($this->getDbConnection()->enableProfiling)
$this->profile('extensions.MongoYii.EMongoDocument.updateAll('.'{$query:'.json_encode($criteria)
.',$document:'.json_encode($updateDoc)
.',$options:'.json_encode($options).'})', 'extensions.MongoYii.EMongoDocument.updateAll');
{
$token = 'extensions.MongoYii.EMongoDocument.query.'.$this->collectionName().'.updateAll('.'{$query:'.json_encode($criteria)
.',$document:'.json_encode($updateDoc)
.',$options:'.json_encode($options).'})';
Yii::beginProfile($token, 'extensions.MongoYii.EMongoDocument.updateAll');
}

$result = $this->getCollection()->update($criteria, $updateDoc, $options);

if($this->getDbConnection()->enableProfiling)
Yii::endProfile($token, 'extensions.MongoYii.EMongoDocument.updateAll');

return $this->getCollection()->update($criteria, $updateDoc, $options);
return $result;
}

/**
Expand All @@ -951,8 +983,14 @@ public function deleteAll($criteria = array(), $options = array()){

Yii::trace('Executing deleteAll: '.'{$query:'.json_encode($criteria).'}','extensions.MongoYii.EMongoDocument');
if($this->getDbConnection()->enableProfiling)
$this->profile('extensions.MongoYii.EMongoDocument.deleteAll('.'{$query:'.json_encode($criteria).'}'.')','extensions.MongoYii.EMongoDocument.deleteAll');
return $this->getCollection()->remove($criteria, array_merge($this->getDbConnection()->getDefaultWriteConcern(), $options));
Yii::beginProfile('extensions.MongoYii.EMongoDocument.query.'.$this->collectionName().'.deleteAll('.'{$query:'.json_encode($criteria).'}'.')','extensions.MongoYii.EMongoDocument.deleteAll');

$result = $this->getCollection()->remove($criteria, array_merge($this->getDbConnection()->getDefaultWriteConcern(), $options));

if($this->getDbConnection()->enableProfiling)
Yii::endProfile('extensions.MongoYii.EMongoDocument.query.'.$this->collectionName().'.deleteAll('.'{$query:'.json_encode($criteria).'}'.')','extensions.MongoYii.EMongoDocument.deleteAll');

return $result;
}

/**
Expand Down Expand Up @@ -1014,7 +1052,7 @@ public function search($query = array(), $project = array(), $partialMatch=false
$this->trace(__FUNCTION__);

foreach($this->getSafeAttributeNames() as $attribute){

$value = $this->{$attribute};
if ($value !== null && $value !== ''){
if((is_array($value) && count($value)) || is_object($value)){
Expand Down Expand Up @@ -1102,7 +1140,7 @@ public function distinct($key, $query = array()){
* @param array $options // All other options for input to the command
* @return mixed
*/
public function mapreduce($map,$reduce,$finalize=null,$out,$query=array(),$options=array()){
public function mapreduce($map,$reduce,$finalize=null,$out,$query=array(),$options=array()){
return $this->getDbConnection()->getDB()->command(array_merge(array(
"mapreduce" => $this->collectionName(),
"map" => $map,
Expand All @@ -1111,8 +1149,8 @@ public function mapreduce($map,$reduce,$finalize=null,$out,$query=array(),$optio
"query" => $query,
"out" => $out
),$options));
}
}

/**
* Refreshes the data from the database
* @return bool
Expand Down Expand Up @@ -1203,14 +1241,4 @@ public function trace($func){
Yii::trace(get_class($this) . '.' . $func . '()', 'extensions.MongoYii.EMongoDocument');
}

/**
* This does our prfiling. There is a reason why this isn't like Yiis own and it is because MongoDB queries are not
* inline as such doing it stepped like in CDbCommand would be pointless. This function acts as nothing more than a log
* to be compatible with certain extensions tbh.
* @param string $token
*/
public function profile($token,$category='extensions.MongoYii.EMongoDocument.query'){
Yii::beginProfile($token,$category);
Yii::endProfile($token,$category);
}
}

0 comments on commit f0521ad

Please sign in to comment.