i’m using big CGridViews (more than 5000 rows, more than 10 cols) and creation takes several seconds and i want to speed this up.
pagination is NOT a option, customer wants to see the whole list
activeRecord is NOT the problem (i’m using CSqlDataProvider)
i tracked down, that the biggest performance problem is caused by the “evaluateExpression” method in CDataColumn, so there isn’t anymore to optimize, or i’m wrong?
so at the moment i think about caching the whole CGridView html code depending on the content.
class CCachedGridView extends CGridView {
public function run() {
$contentStr=$this->dataProvider->getSort()->getOrderBy();
foreach ($this->dataProvider->data as $row) {
foreach ($row as $col) {
$contentStr.=$col;
}
}
$contentHash=hash ("md5", $contentStr);
$listHtmlCode=Yii::app()->cache->get($contentHash);
if($listHtmlCode===false) {
ob_start();
parent::run();
$listHtmlCode = ob_get_clean();
Yii::app()->cache->set($contentHash, $listHtmlCode);
}
echo $listHtmlCode;
}
}
is this a good idea? or are there any better ways to do?
I expect that you’re also losing a lot of time in transferring the data and in the browser building and calculating the layout. Can you show the code you’re using in the view to build the columns?
yes you are right, the browser building is slow, too.
the column-build process is really complex, because the user can customize (add, remove, order) the columns of the table. this means the column-defintion AND the sql query gets generated dynamically. this part isn’t the performance problem. to problem are the col definitons like:
this takes lot of time during the "evaluateExpression"-step
oh thanks for the hint, so i fought it down to:
class CCachedGridView extends CGridView {
public function run() {
$contentStr=$this->dataProvider->getSort()->getOrderBy();
foreach ($this->dataProvider->data as $row) {
foreach ($row as $col) {
$contentStr.=$col;
}
}
$contentHash=hash ("md5", $contentStr);
if($this->beginCache($contentHash)) {
parent::run();
$this->endCache();
}
}
}
the problem is: it is an re-implementation of a old php software, and the old php script (a HUGE unreadable foreach loop) created this 5000 rows table in less than 1 second . so the customer WANT to see all the rows on one site with the same performance like the old script
I don’t quite get why you would need [font=“Courier New”]stripslashes()[/font] in your expression. As for hiding columns: You are aware of CGridColumn.visible? Also, specifying [font=“Courier New”]‘type’=>‘html’[/font] in the column definition will spare you the call to [font=“Courier New”]CHtml::encode()[/font] in your expression. I think trimming the fat out of that one is really the key. If that doesn’t work, I’d be close to suggesting not using a grid view at all and rendering the table the good ol’ way …
Oh, by the way: Fragment caching is something you usually do in the view, not the controller
stripslashes is needed, because the slashes are saved in the database (created with an old software)
thansk for the type-hint, this solved my problem, but in another way: after setting type to "raw", the performance improved massively (caching is no longer needed, page needs ca 2 seconds to generate, thats ok)