Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Why Large Pages have Slow JS

Status
Not open for further replies.

Meleagant

Programmer
Aug 31, 2001
166
US
All,

I've been searching the interwebs and haven't found a "scientific" answer.

I built a rather nice business application, with a fatal drawback. I rely heavily on tables, not because I want to but because I need to display 3 - 5K of detail records. Basically each screen is a table with data and a couple of other buttons.

The grid loads via an Ajax call and the TR/TD tags are created in a JS loop.

-- There are onclick and dblclick events on my rows.
-- Cells widths are set in pixels
-- External (& minimized) JS & Css files.

If I view the generated source of the page it is around 3.5MB. View-state is negligible since the table is client side only.

What I am looking for is an answer as to why JS becomes very sluggish as the page size increases. If I click a button that has nothing to do with the grid, why does it take 1 minute plus for the event to fire?

* Sine scientia ars nihil est
* Respondeat superior
 
Hi

Meleagant said:
What I am looking for is an answer as to why JS becomes very sluggish as the page size increases.
Because of careless programming style.

If you are not satisfied by my answer, show us your code. Then we will be able to tell you where in your code is the problem.

Feherke.
 
[ ]

It appears that you are dynamically building your tables with data that changes between every build of the table.

If not, why use javascript at all?

mmerlinn


"We've found by experience that people who are careless and sloppy writers are usually also careless and sloppy at thinking and coding. Answering questions for careless and sloppy thinkers is not rewarding." - Eric Steven Raymond
 
Uhhh...not sure how to respond to either post. My question was more of a general nature, rather than specifics. May be "general" is not the correct word, what I am looking for is what exactly does IE have to do to execute an event. Does is have to parse/read through the whole page before the JS event is carried out? What is it about large pages that makes JS sluggish.

If it helps here is the code
The Web Service Call
Code:
HWCSoft.CostAcctWebService.CostAcctData.GetGLData(_dbId, effDate, months, OnGotGLData, OnError, OnTimeOut);

The "OnSucess" Functions

* ** Just a note that the data comes back as a big string. Row delimiter is vbCr & Cell delimiter is "|". Timing the entire server function it takes around 1sec to execute the query and put together the string.

* ** Also note so that I can have a frozen header/footer row I am using the nested table & CSS technique. There is a parent table with 3 rows (Header table, Detail Table & Footer (when needed)).

Code:
function OnGotGLData(arg) {
	window.status = 'Loading General Ledger Data...';
	tblGL_FillData(arg, getTableRef(tableId));

	window.status = 'Done';
	Indicator_Hide('divIndicator');
}

function tblGL_FillData(tableItems, oParentTbl) {
	window.status = 'Populating Detail Table...';
	
	if (tableItems === '' || tableItems.length === 0) { 
		return; 
	}

	var rowItems = [];
	rowItems = tableItems.split(recDelimiter);
	
	var oHdrTbl = oParentTbl.rows[0].cells[0].firstChild.firstChild;
	var oDtlTbl = oParentTbl.rows[1].cells[0].firstChild.firstChild;
	
	ClearTable(oParentTbl);
	
	/* ** SetUp Sort Image on Columns ** */
	SetColumnSortImages(oHdrTbl);
	
	/* ** Populate the Table with Data ** */
	var cellItem = [];
	var oRow = {};
	var oCell = {};
	var j = 0
	var numCols = 0;
	for (var i = 0; i < rowItems.length; i++) {

		cellItem = rowItems[i].split(fldDelimiter);
		if (cellItem[0] === '') {
			continue;
		}

		oRow = document.createElement('TR');
		oRow.className = (i % 2) == 0 ? 'tvRow' : 'tvAltRow';

		numCols = cellItem.length;
		
		for (j = 0; j < numCols; j++) {
			oCell = document.createElement('TD');
			
			oCell.innerText = cellItem[j];
			oCell.align = oHdrTbl.rows[0].cells[j].align;
			
			if (i === 0) {
				oCell.style.width = oHdrTbl.rows[0].cells[j].style.width;
			}
			oRow.appendChild(oCell);
		}
		
		oRow.onmouseover = function() {SetNewColor(this);};
		oRow.onmouseout = function() {SetOldColor(this);};
		oRow.onclick = function() {tblGL_RowClick(this);};
		
		oDtlTbl.firstChild.appendChild(oRow)
	}

	window.status = 'Done';

}

That's pretty much it. Of course there is other code on the page, the functions for the onClick, onMouseEvents, etc. But this is how I create my data table. Tables created with < 1000 rows work great. Tables with 3 - 5K rows will frequently send IE into "Not Responding" when trying to click a row or another button elsewhere on the page that does not have anything to do with the grid.

For the hec of it here is the server-side piece:
Code:
Public Shared Function sqlGetGLData(ByVal dbId As String, ByVal EffectiveDate As String, ByVal Months As String) As String

	Dim retVal As New StringBuilder

	Dim ConnStr As String = cConnStr
	Dim SqlStr As String = ""

	Try
		If Months = "" Then Months = "0"

		If EffectiveDate = "" Then
			SqlStr = String.Format("exec GetGLData {0}, '', {1}", dbId, Months)

		Else
			Dim effDate As Date = Now
			Date.TryParse(EffectiveDate, effDate)

			SqlStr = String.Format("exec GetGLData {0}, '{1}', {2}", dbId, effDate.ToString("yyyyMMdd"), Months)

		End If

		Dim rdr As SqlClient.SqlDataReader
		rdr = SqlHelper.ExecuteReader(ConnStr, CommandType.Text, SqlStr)

		While rdr.Read
			retVal.AppendFormat("{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}{8}", rdr("AcctNum").ToString, rdr("ObjCode").ToString, rdr("AcctDesc").ToString, rdr("ObjDesc").ToString, rdr("ActualMonth").ToString, rdr("ActualYTD").ToString, rdr("BudgetMonth").ToString, rdr("BudgetYTD").ToString, vbCr)
		End While

	Catch ex As Exception
		SendErrorEmail(ex)

	End Try

	Return retVal.ToString.TrimEnd(CChar(vbCr))

End Function

* Sine scientia ars nihil est
* Respondeat superior
 
Hi

Then a generic advice : instead of [tt]oRow=document.createElement('TR')[/tt] and [tt]oCell=document.createElement('TD')[/tt] try using [tt]oRow=oDtlTbl.insertRow(-1)[/tt] and [tt]oCell=oRow.insertCell(-1)[/tt]. ( And of course remove the [tt]appendChild()[/tt] calls for them. )

Feherke.
 
Thanks for the advice. Tried it, completely froze IE. Added the insertRow and removed the appendChild. Refreshed my page and nothing. The grid started it's load function, but never finished. Browser froze not soon after.



* Sine scientia ars nihil est
* Respondeat superior
 
One curious observation...

I built in a simple filter functionality into these grids. If whatever value in whatever cell does not match what I am filtering for, the row's class is set to "hideMe" (basically oElement.style.display="none").

If I filter my grid so it only displays 100 or so rows, the page as a whole will be much quicker. But, I still have the same amount of stuff on the page. The page's size suddenly didn't shrink just because some TR elements have their display properties set to none.

So... Why would my page be quicker when elements are hidden? The page is the same size, there are the same number of elements in the DOM. Is my sluggish JS problem related to the number of elements that the browser has to draw? Dunno, anyone hazard a guess?


* Sine scientia ars nihil est
* Respondeat superior
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top