PDA

View Full Version : grid addRows performance



ericwaldheim
18 Oct 2006, 11:48 AM
The dm.addRows call for 364 rows * 15 cols takes longer than I want the user to wait (9 seconds on my browser).

What is the right approach to speed this up?

I do not need a LoadableDataModel as all my data is already available.
I just want the grid to draw a page and then draw other pages on demand but
as I peruse the code it seems that the DefaultDataModel does not support paging.

I assume I want to write a DataModel based on DefaultDataModel and then add paging?

I'd appreciate if you could point me in the right direction.
Thank you,
Eric

devol
18 Oct 2006, 1:51 PM
The bottleneck for me was the column resizing support. Do you need resiziable columns? I think Jack is working on a speedup that turns that off.

jack.slocum
18 Oct 2006, 4:28 PM
If the user has sorted and you are using in-browser sorting that can slow it down too since it will sort the incoming data.

For local data you could try this, but it's a hack and it won't maintain sorting:

dataModel.data = yourNewData;
dataModel.fireTableDataChanged();

As for paging, that would really speed up the rendering if you could do it in paged blocks. You could extend DefaultDataModel and add the required methods (there's only a few defined in LoadableDataModel) to support paging from the local array. If you get this working I'd love a copy to include with the library if you are willing to share. If you have any problems implementing it, I'd be happy to answer any questions.

ericwaldheim
19 Oct 2006, 8:51 AM
Well, here's an attempt. When I enter a page number in the toolbar, it goes to the correct page.
(I see no effect when I click the Toolbar buttons though, I imagine that's an unrelated problem.)

I added a data member called "allData" to hold all rows, and a member function called setAllRows to set it as well as the totalCount data member.
But would having dm.data hold all rows and adding a dm.pagedData makes more sense?
Then the inherited DefaultDataModel functions will still operate on all the data.
I imagine then that PagedDataModel.getValueAt would take the pageNum into account.
Should I give that a try instead?

(P.S. I've decided against paging and am going to try the other speedups mentioned but I'm willing to keep hacking here as well)



/*
* YUI Extensions
* Copyright(c) 2006, Jack Slocum.
*
* This code is licensed under BSD license.
* http://www.opensource.org/licenses/bsd-license.php
*/

/**
* @class
* This class extends DefaultDataModel and adds the core functionality to load data remotely.


* @extends YAHOO.ext.grid.DefaultDataModel
* @constructor
* @param {String} dataType YAHOO.ext.grid.PagedDataModel.XML, YAHOO.ext.grid.PagedDataModel.TEXT or YAHOO.ext.grid.JSON
*/
YAHOO.ext.grid.PagedDataModel = function(data){
YAHOO.ext.grid.PagedDataModel.superclass.constructor.call(this, []);
this.allData = data;

/** Fires when a successful load is completed - fireDirect sig: (this)
* @type YAHOO.util.CustomEvent
* @deprecated Use addListener instead of accessing directly
*/
this.onLoad = new YAHOO.util.CustomEvent('load');
/** Fires when a load fails - fireDirect sig: (this, errorMsg, responseObj)
* @type YAHOO.util.CustomEvent
* @deprecated Use addListener instead of accessing directly
*/
this.onLoadException = new YAHOO.util.CustomEvent('loadException');

this.events['load'] = this.onLoad;
this.events['beforeload'] = new YAHOO.util.CustomEvent('beforeload');
this.events['loadexception'] = this.onLoadException;

// paging info
/** The active page @type Number*/
this.loadedPage = 1;
/** True to use remote sorting, initPaging automatically sets this to true @type Boolean */
this.remoteSort = false;
/** The number of records per page @type Number*/
this.pageSize = 0;
/** An object of key/value pairs to be passed as parameters
* when loading pages/sorting @type Object*/
this.baseParams = {};
/** Maps named params to url parameters - Override to specify your own param names */
this.paramMap = {'page':'page', 'pageSize':'pageSize', 'sortColumn':'sortColumn', 'sortDir':'sortDir'};

};
YAHOO.extendX(YAHOO.ext.grid.PagedDataModel, YAHOO.ext.grid.DefaultDataModel);

/** @ignore */
YAHOO.ext.grid.PagedDataModel.prototype.setLoadedPage = function(pageNum, userCallback){
this.loadedPage = pageNum;
if(typeof userCallback == 'function'){
userCallback();
}
};

/** Returns true if this model uses paging @type Boolean */
YAHOO.ext.grid.PagedDataModel.prototype.isPaged = function(){
return this.pageSize > 0;
};

/** Returns the total number of records available, override if needed @type Number */
YAHOO.ext.grid.PagedDataModel.prototype.getTotalRowCount = function(){
return this.totalCount || this.getRowCount();
};

/** Returns the number of records per page @type Number */
YAHOO.ext.grid.PagedDataModel.prototype.getPageSize = function(){
return this.pageSize;
};

/** Returns the total number of pages available @type Number */
YAHOO.ext.grid.PagedDataModel.prototype.getTotalPages = function(){
if(this.getPageSize() == 0 || this.getTotalRowCount() == 0){
return 1;
}
return Math.ceil(this.getTotalRowCount()/this.getPageSize());
};

/** Initializes paging for this model. */
YAHOO.ext.grid.PagedDataModel.prototype.initPaging = function(pageSize, baseParams){
this.pageSize = pageSize;
this.remoteSort = false;
if(baseParams) this.baseParams = baseParams;
};

/** @ignore */
YAHOO.ext.grid.PagedDataModel.prototype.createParams = function(pageNum, sortColumn, sortDir){
var params = {}, map = this.paramMap;
for(var key in this.baseParams){
if(typeof this.baseParams[key] != 'function'){
params[key] = this.baseParams[key];
}
}
params[map['page']] = pageNum;
params[map['pageSize']] = this.getPageSize();
params[map['sortColumn']] = (typeof sortColumn == 'undefined' ? '' : sortColumn);
params[map['sortDir']] = sortDir || '';
return params;
};

YAHOO.ext.grid.PagedDataModel.prototype.loadPage = function(pageNum, callback, keepExisting){
var sort = this.getSortState();
var params = this.createParams(pageNum, sort.column, sort.direction);
this.load(this.pageUrl, params, this.setLoadedPage.createDelegate(this, [pageNum, callback]),
keepExisting ? (pageNum-1) * this.pageSize : null);
};

/** @ignore */
YAHOO.ext.grid.PagedDataModel.prototype.applySort = function(suppressEvent){
if(!this.remoteSort){
YAHOO.ext.grid.PagedDataModel.superclass.applySort.apply(this, arguments);
}else if(!suppressEvent){
var sort = this.getSortState();
if(sort.column){
this.fireRowsSorted(sort.column, sort.direction, true);
}
}
};

/** @ignore */
YAHOO.ext.grid.PagedDataModel.prototype.resetPaging = function(){
this.loadedPage = 1;
};

/** Overridden sort method to use remote sorting if turned on */
YAHOO.ext.grid.PagedDataModel.prototype.sort = function(columnModel, columnIndex, direction, suppressEvent){
if(!this.remoteSort){
YAHOO.ext.grid.PagedDataModel.superclass.sort.apply(this, arguments);
}else{
this.columnModel = columnModel;
this.sortColumn = columnIndex;
this.sortDir = direction;
var params = this.createParams(this.loadedPage, columnIndex, direction);
this.load(this.pageUrl, params, this.fireRowsSorted.createDelegate(this, [columnIndex, direction, true]));
}
}
/**
* Initiates the loading of the data from the specified URL - Failed load attempts will
* fire the {@link #onLoadException} event.
* @param {Object/String} url The url from which the data can be loaded
* @param {String/Object} params (optional) The parameters to pass as either a url encoded string "param1=1&param2=2" or as an object {param1: 1, param2: 2}
* @param {Function} callback (optional) Callback when load is complete - called with signature (this, rowCountLoaded)
* @param {Number} insertIndex (optional) if present, loaded data is inserted at the specified index instead of overwriting existing data
*/
YAHOO.ext.grid.PagedDataModel.prototype.load = function(url, params, callback, insertIndex){
this.fireEvent('beforeload');
var keepExisting = (typeof insertIndex == 'number');
try{
var pageNum = params[this.paramMap['page']];
this.loadedPage = pageNum;
var pageSize = this.getPageSize();
var first = (pageNum - 1) * pageSize;
var pageRows = this.allData.slice(first, first + pageSize);
if(keepExisting !== true){
this.removeAll();
}
this.addRows(pageRows);
if(typeof callback == 'function'){
callback(this, true);
}
this.fireLoadEvent();
}catch(e){
this.fireLoadException(e, null);
if(typeof callback == 'function'){
callback(this, false);
}
}
};

YAHOO.ext.grid.PagedDataModel.prototype.setAllRows = function(data){
this.allData = data;
this.totalCount = data.length;
}

/**@private*/
YAHOO.ext.grid.PagedDataModel.prototype.processException = function(response){
this.fireLoadException(null, response);
if(typeof response.argument.callback == 'function'){
response.argument.callback(this, false);
}
};

YAHOO.ext.grid.PagedDataModel.prototype.fireLoadException = function(e, responseObj){
this.onLoadException.fireDirect(this, e, responseObj);
};

YAHOO.ext.grid.PagedDataModel.prototype.fireLoadEvent = function(){
this.fireEvent('load', this.loadedPage, this.getTotalPages());
};

ericwaldheim
19 Oct 2006, 10:40 AM
The bottleneck for me was the column resizing support. Do you need resiziable columns? I think Jack is working on a speedup that turns that off.

yep, resizable columns are a requirement.
thanks.