<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
	<title>jQuery Grid Plugin - jqGrid - Topic: small performance improvements in selectors</title>
	<link>http://www.trirand.com/blog/?page_id=393/bugs/small-performance-improvements-in-selectors</link>
	<description><![CDATA[Grid plugin]]></description>
	<generator>Simple:Press Version 5.7.5.3</generator>
	<atom:link href="http://www.trirand.com/blog/?page_id=393/bugs/small-performance-improvements-in-selectors/rss" rel="self" type="application/rss+xml" />
        <item>
        	<title>OlegK on small performance improvements in selectors</title>
        	<link>http://www.trirand.com/blog/?page_id=393/bugs/small-performance-improvements-in-selectors#p26631</link>
        	<category>Bugs</category>
        	<guid isPermaLink="true">http://www.trirand.com/blog/?page_id=393/bugs/small-performance-improvements-in-selectors#p26631</guid>
        	        	<description><![CDATA[<p>Hallo Tony,</p>
<p>I wanted to wrote the post already befor, but doing it only now. There are exist small performance issue in jqGrid with the usage of pseudo-selectors like <strong>:first</strong>&#160;or <strong>:gt</strong>&#160;for example. If you look in the current version of jQuery documentation (for example <a href="http://api.jquery.com/first-selector/" target="_blank">here</a>) you will find the following</p>
<blockquote>
<p>Because <strong>:first</strong> is a jQuery extension and not part of the CSS specification, queries using <strong>:first</strong> cannot take advantage of the performance boost provided by the native DOM <strong>querySelectorAll()</strong> method. To achieve the best performance when using <strong>:first</strong> to select elements, first select the elements using a pure CSS selector, then use <strong>.filter(":first")</strong>.</p>
</blockquote>
<p>One can seen the problem in Developer Tools of Chrome very clear. First of all one should open Developer Tools (for example with Ctrl-Shift-J), choose "Scripts" tab and then enable the following button:</p>
<p><a href="http://www.ok-soft-gmbh.com/jqGrid/PauseOnExceptions.png"><img src="http://www.ok-soft-gmbh.com/jqGrid/PauseOnExceptions.png" width="100"  class="sfimageleft spUserImage" alt="" /><img src="http://www.trirand.com/blog/wp-content/sp-resources/forum-themes/default/images/sp_Mouse.png" class="sfimageleft sfmouseleft" alt="Image Enlarger" /></a></p>
<p>After that one can load any test page which uses jqGrid. For example one can load <a href="http://www.ok-soft-gmbh.com/jqGrid/Test1.htm" target="_blank">the demo</a>. During loading the page one will see that some exceptions was thrown which origing was pseudo-selectors used in jqGrid. One will see the picture like below</p>
<p><a href="http://www.ok-soft-gmbh.com/jqGrid/Exceptions-first.png"><img src="http://www.ok-soft-gmbh.com/jqGrid/Exceptions-first.png" width="100"  class="sfimageleft spUserImage" alt="" /><img src="http://www.trirand.com/blog/wp-content/sp-resources/forum-themes/default/images/sp_Mouse.png" class="sfimageleft sfmouseleft" alt="Image Enlarger" /></a></p>
<p>The exceptions will be in the <strong>querySelectorAll</strong> function in <a href="https://github.com/jquery/sizzle/blob/master/sizzle.js#L1221" target="_blank">the line</a> of jQuery code. The problem is that jQuery don&#39;t parse selectors for not common supported pseudo selectors. And how one can see on <a href="http://www.w3.org/TR/css3-selectors/#selectors" target="_blank">w3</a> the <strong>:first</strong> is not in the list of supported selectors.</p>
<p>During loaging of the demo one will see exceptions in the following selectors:</p>
<p>"#list tbody:first"<br />"#list tbody:first tr:first"<br />"table:first"<br />"tr:first"<br />"thead:first"<br />"thead tr:first th"</p>
<p>One can fix the problem and improve a little the performance in at least one from the following ways</p>
<ol>
<li>one can use <strong>:nth-of-type(1)</strong>&#160;selector (see <a href="http://www.javascriptkit.com/dhtmltutors/css_selectors_api.shtml" target="_blank">the post</a>) instead <strong>:first</strong>, but it&#39;s not good way because <strong>:nth-of-type(1)</strong>&#160;selector is not supported by old browsers.</li>
<li>one can replace the code like <a href="https://github.com/tonytomov/jqGrid/blob/v4.3.2/js/grid.base.js#L1221" target="_blank">$("tbody:first",t)</a>&#160;to <strong>$("tbody",t).eq(0)</strong> and it will works without any problem and will work quickly.</li>
<li>One can use <strong>slice(1)</strong> instead of <strong>:gt(0)</strong>. For example the expression <a href="https://github.com/tonytomov/jqGrid/blob/v4.3.2/js/grid.base.js#L1049" target="_blank">$("#"+$.jgrid.jqID(ts.p.id)+" tbody:first tr:gt(0)").remove();</a>&#160;from code of <strong>emptyRows</strong> one can simplify to <strong>$(ts.rows).slice(1).remove();</strong>.</li>
<li>In some places one can rewrite the existing selectors where <strong>:first</strong>&#160;so that <strong>:first-child</strong> or <strong>:last-child</strong> will be used. For example <strong>tbody:first</strong>&#160;or <strong>&#62;</strong><strong>tbody:first</strong>&#160;will be frequently used to select tbody inside of grid or grid header div. In the case one can use <strong>:first-child</strong>. The selector <strong>$(&#39;table:first&#39;,this.hDiv)</strong> like <a href="https://github.com/tonytomov/jqGrid/blob/v4.3.2/js/grid.base.js#L810" target="_blank">here</a> can be rewritten as <strong>$(this.hDiv).find(</strong><strong>&#39;&#62;div&#62;table:first-child&#39;</strong>). In the same way <strong>$(&#39;table:first&#39;,this.bDiv)</strong> selector from <a href="https://github.com/tonytomov/jqGrid/blob/v4.3.2/js/grid.base.js#L809" target="_blank">the previous line</a>&#160;can be rewritten as <strong>$(this.bDiv).find(&#39;&#62;div&#62;table:last-child&#39;)</strong>. One can&#39;t use <strong>:first-child</strong>&#160;here because the first child are empty div. Instead of <strong>$(this.hDiv).find(&#39;&#62;div&#62;table:first-child&#39;)</strong> one can use <strong>$(this.hDiv).find(&#39;&#62;div:first-child&#62;table:first-child&#39;)</strong> or <strong>$(this.hDiv).find(&#39;&#62;:first-child&#62;table:first-child&#39;)</strong>. In the same way instead of <strong>$(this.bDiv).find(&#39;&#62;div&#62;table:last-child&#39;)</strong>&#160;one can use <strong>$(this.bDiv).find(&#39;&#62;div</strong><strong>:first-child</strong>&#62;table:last-child&#39;)&#160;or <strong>$(this.bDiv).find(&#39;&#62;</strong><strong>:first-child</strong>&#62;table:last-child&#39;). In all the selectors it will be no exception and the full searching will be made in the <em>native</em> code by <strong>querySelectorAll</strong> function.</li>
</ol>
<p>In the way one can eliminate exceptions which improve the performance itself. Additionally rewriting selectors to the form which produce <em>one</em>&#160;element as the result instead of array and usage of <strong>eq(0)</strong> will improve the performance additionally because the&#160;<strong>querySelectorAll</strong>&#160;function are implemented in <em>native</em> code of modern browsers and so gives us the best performance.</p>
<p>I understand, that all the described performance improvements could be not always so extrem visible, but I recommend to do there nevertheless. The more modern web browsers will be used the more large will be the performance advantage from the changes.</p>
<p>Best regards<br />Oleg&#160;</p>
]]></description>
        	        	<pubDate>Fri, 18 May 2012 16:33:31 +0300</pubDate>
        </item>
</channel>
</rss>