<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>30988</bug_id>
          
          <creation_ts>2009-10-31 21:35:53 -0700</creation_ts>
          <short_desc>Attribute cache purged too eagerly</short_desc>
          <delta_ts>2017-07-18 08:29:24 -0700</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>WebCore Misc.</component>
          <version>528+ (Nightly build)</version>
          <rep_platform>All</rep_platform>
          <op_sys>All</op_sys>
          <bug_status>UNCONFIRMED</bug_status>
          <resolution></resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords></keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>0</everconfirmed>
          <reporter name="James Robinson">jamesr</reporter>
          <assigned_to name="Nobody">webkit-unassigned</assigned_to>
          <cc>hamaji</cc>
    
    <cc>paranoid.android.dev</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>159611</commentid>
    <comment_count>0</comment_count>
    <who name="James Robinson">jamesr</who>
    <bug_when>2009-10-31 21:35:53 -0700</bug_when>
    <thetext>The following code runs in O(N) time on Firefox and O(N^2) time on WebKit based browsers:

  var elems = document.getElementsByName(&apos;elem_name&apos;);
  for (var i=0; i&lt;elems.length; i++) {
    var e = elems.item(i);
    e.className = &apos;elem_class&apos;;
  }

document.getElementsByName() returns a NodeList which is backed by a WebCore::DynamicNodeList.  The reason for the slowdown is that assigning to e.className forces the document&apos;s entire node list cache to be dumped, even though the DynamicNodeList backing the &apos;elems&apos; variable has nothing to do with the class name attribute.  This means in each loop iteration the &apos;elems&apos; variable has to be recalculated by evaluating every node in the entire DOM to see if its name is &apos;elem_name&apos;.  There&apos;s two obvious optimizations that can be made:

1) When an attribute is mutated only purge node list caches associated with the attribute mutated
2) When an attribute with value X has X written into it (i.e. if the className was already &apos;elem_class&apos; in this example), do not purge any node list caches

It&apos;s of course possible to rewrite the javascript snippet to perform much better by copying the elements in &apos;elems&apos; into a javascript array before mutating them, but I think the javascript is fairly idiomatic and reasonable.  Additionally since Firefox performs fine on this code developers are less likely to notice how badly this performs.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>159614</commentid>
    <comment_count>1</comment_count>
      <attachid>42268</attachid>
    <who name="James Robinson">jamesr</who>
    <bug_when>2009-10-31 21:39:27 -0700</bug_when>
    <thetext>Created attachment 42268
Test page to see behavior

Attached is a simple test page to try out.  There&apos;s three versions of the loop - the naive solution from the bug report, a version that stores the &apos;length&apos; property in a javascript variable, and a version that copies the entire node list into a javascript array before mutating values.  On a pretty recent WebKit nightly in Safari on OS X I get these times:

time elapsed (naive) for 5000 was 1490 ms
time elapsed (naive) for 5000 was 1393 ms
time elapsed (cache length) for 5000 was 471 ms
time elapsed (cache length) for 5000 was 481 ms
time elapsed (cache array) for 5000 was 10 ms
time elapsed (cache array) for 5000 was 10 ms

On Firefox 3.5.4 on OS X I get these times:

time elapsed (naive) for 5000 was 82 ms
time elapsed (naive) for 5000 was 24 ms
time elapsed (cache length) for 5000 was 128 ms
time elapsed (cache length) for 5000 was 13 ms
time elapsed (cache array) for 5000 was 130 ms
time elapsed (cache array) for 5000 was 29 ms</thetext>
  </long_desc>
      
          <attachment
              isobsolete="0"
              ispatch="0"
              isprivate="0"
          >
            <attachid>42268</attachid>
            <date>2009-10-31 21:39:27 -0700</date>
            <delta_ts>2009-10-31 21:39:27 -0700</delta_ts>
            <desc>Test page to see behavior</desc>
            <filename>name.html</filename>
            <type>text/html</type>
            <size>2127</size>
            <attacher name="James Robinson">jamesr</attacher>
            
              <data encoding="base64">PGh0bWw+CjxoZWFkPgo8c3R5bGU+Ci5lbGVtX2NsYXNzIHsgY29sb3I6IHJlZH0KLmVsZW1fY2xh
c3MyIHsgY29sb3I6IGdyZWVufQouZWxlbV9jbGFzczMgeyBjb2xvcjogYmx1ZX0KPC9zdHlsZT4K
PHNjcmlwdD4KZnVuY3Rpb24gbG9nKHMpIHsKICB2YXIgZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1l
bnQoJ2RpdicpOwogIGQuaW5uZXJIVE1MID0gczsKICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgn
bG9nJykuYXBwZW5kQ2hpbGQoZCk7CiAgY29uc29sZS5sb2cocyk7Cn0KCmZ1bmN0aW9uIHRlc3Qo
KSB7CiAgdmFyIHN0YXJ0VGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpOwogIHZhciBlbGVtcyA9
IGRvY3VtZW50LmdldEVsZW1lbnRzQnlOYW1lKCdlbGVtX25hbWUnKTsKICBmb3IgKHZhciBpPTA7
IGk8ZWxlbXMubGVuZ3RoOyBpKyspIHsKICAgIHZhciBlID0gZWxlbXMuaXRlbShpKTsKICAgIGUu
Y2xhc3NOYW1lID0gJ2VsZW1fY2xhc3MnOwogIH0KICB2YXIgZW5kVGltZSA9IG5ldyBEYXRlKCku
Z2V0VGltZSgpOwogIGxvZygidGltZSBlbGFwc2VkIChuYWl2ZSkgZm9yICIgKyBlbGVtcy5sZW5n
dGggKyAiIHdhcyAiCiAgICAgICAgICAgICAgKyAoZW5kVGltZSAtIHN0YXJ0VGltZSkgKyAiIG1z
Iik7Cn0KCmZ1bmN0aW9uIHRlc3QyKCkgewogIHZhciBzdGFydFRpbWUgPSBuZXcgRGF0ZSgpLmdl
dFRpbWUoKTsKICB2YXIgZWxlbXMgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5TmFtZSgnZWxlbV9u
YW1lJyk7CiAgdmFyIGwgPSBlbGVtcy5sZW5ndGg7CiAgZm9yICh2YXIgaT0wOyBpPGw7IGkrKykg
ewogICAgdmFyIGUgPSBlbGVtcy5pdGVtKGkpOwogICAgZS5jbGFzc05hbWUgPSAnZWxlbV9jbGFz
czInOwogIH0KICB2YXIgZW5kVGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpOwogIGxvZygidGlt
ZSBlbGFwc2VkIChjYWNoZSBsZW5ndGgpIGZvciAiICsgZWxlbXMubGVuZ3RoICsgIiB3YXMgIgog
ICAgICAgICAgICAgICsgKGVuZFRpbWUgLSBzdGFydFRpbWUpICsgIiBtcyIpOwp9CgpmdW5jdGlv
biB0ZXN0MygpIHsKICB2YXIgc3RhcnRUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7CiAgdmFy
IGVsZW1zID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeU5hbWUoJ2VsZW1fbmFtZScpOwogIHZhciBs
ID0gZWxlbXMubGVuZ3RoOwogIHZhciBlbGVtc0FyciA9IFtdOwogIGZvciAodmFyIGk9MDsgaTxs
OyBpKyspIHsKICAgIGVsZW1zQXJyLnB1c2goZWxlbXMuaXRlbShpKSk7CiAgfQogIGZvciAodmFy
IGk9MDsgaTxsOyBpKyspIHsKICAgIHZhciBlID0gZWxlbXNBcnJbaV07CiAgICBlLmNsYXNzTmFt
ZSA9ICdlbGVtX2NsYXNzMyc7CiAgfQogIHZhciBlbmRUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1l
KCk7CiAgbG9nKCJ0aW1lIGVsYXBzZWQgKGNhY2hlIGFycmF5KSBmb3IgIiArIGVsZW1zLmxlbmd0
aCArICIgd2FzICIKICAgICAgICAgICAgICArIChlbmRUaW1lIC0gc3RhcnRUaW1lKSArICIgbXMi
KTsKfQoKd2luZG93Lm9ubG9hZCA9IGZ1bmN0aW9uKCkgewogIHZhciByb290ID0gZG9jdW1lbnQu
Z2V0RWxlbWVudEJ5SWQoJ3Jvb3QnKTsKICBmb3IgKHZhciBpPTA7IGk8NTA7IGkrKykgewogICAg
dmFyIHIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsKICAgIGZvciAodmFyIGo9MDsg
ajwxMDA7IGorKykgewogICAgICB2YXIgZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2Rpdicp
OwogICAgICBkLnNldEF0dHJpYnV0ZSgnbmFtZScsICdlbGVtX25hbWUnKTsKICAgICAgZC5pbm5l
ckhUTUwgPSAnYSc7CiAgICAgIHIuYXBwZW5kQ2hpbGQoZCk7CiAgICB9CiAgICByb290LmFwcGVu
ZENoaWxkKHIpOwogIH0KfQo8L3NjcmlwdD4KPC9oZWFkPgo8Ym9keT4KPGRpdiBvbmNsaWNrPSJq
YXZhc2NyaXB0OnRlc3QoKSI+Y2xpY2sgdG8gdGVzdCBuYWl2ZSBsb29wPC9kaXY+CjxkaXYgb25j
bGljaz0iamF2YXNjcmlwdDp0ZXN0MigpIj5jbGljayB0byB0ZXN0IGNhY2hpbmcgbGVuZ3RoPC9k
aXY+CjxkaXYgb25jbGljaz0iamF2YXNjcmlwdDp0ZXN0MygpIj5jbGljayB0byB0ZXN0IGNhY2hp
bmcgYXJyYXk8L2Rpdj4KPGRpdiBpZD0ibG9nIj48L2Rpdj4KPGRpdiBpZD0icm9vdCI+PC9kaXY+
CjwvYm9keT4KPC9odG1sPgoK
</data>

          </attachment>
      

    </bug>

</bugzilla>