[Prototype-core] Re: Element#siblings
I poked around even more to see if there could be anythings improved. I added tests for querySelectorAll, Xpath and native nextSiblingElement (if present). Alas, with qsa is quite tricky to simulate siblings -- I had to set and unset attributes to achieve it and to use [] and :not selectors. XPath has rules for siblings (preceding and following, but not all) -- fairly simple, but quite slow (why?). While in FF 3.5.2 siblingsKangax rulles them all in Opera 9.5 and Chromium Portable things tend to be different. http://groups.google.com/group/prototype-core/web/element%23siblings%20%282%29.zip On Sep 3, 4:47 pm, kangax wrote: > `adHocSiblings` is clearly faster. I guess since it avoids 2 extra > function calls (`previousSiblings` and `nextSiblings`). > > Running a simple test based on your example page: > > var tdEl = document.getElementsByTagName('td')[100]; > > var t = new Date(); > for (var i=1000; i--; ) protoSiblings(tdEl); > var t1 = new Date() - t; > > t = new Date(); > for (var i=1000; i--; ) adHocSiblings(tdEl); > var t2 = new Date() - t; > > t = new Date(); > for (var i=1000; i--; ) siblings2(tdEl); > var t3 = new Date() - t; > > document.write( > 'protoSiblings: ' + t1 + 'ms;'+ > 'adHocSiblings: ' + t2 + 'ms;'+ > 'siblings2: ' + t3 + 'ms'); > > where `siblings2` is practically your `adHocSiblings`, but with few > more optimizations (such as do-while instead of while-do, as well as > removal of `push` and `arguments`) - > > function siblings2(element) { > if (!element) return []; > var originalElement = element, elements = [], i = 0; > element = element.parentNode.firstChild; > do { > if (element.nodeType == 1 && element != originalElement) { > elements[i++] = element; > } > } while (element = element.nextSibling) > return elements; > > } > > === FF 3.5.2 > protoSiblings: 41ms; > adHocSiblings: 23ms; > siblings2: 19ms > > === Opera 10 > protoSiblings: 78ms; > adHocSiblings: 61ms; > siblings2: 45ms > > === Safari 3.2.1 > protoSiblings: 28ms; > adHocSiblings: 17ms; > siblings2: 14ms > > -- > kangax > > On Sep 3, 5:33 am, Иван Жеков wrote: > > > Actually I did make a test case > > --http://groups.google.com/group/prototype-core/web/element%23siblings > > zipped to take less space from the quota. > > > For fair tests, I extracted the methods as simple functions. > > > Note: > > * The first click is noticably slower then the rest of the clicks. > > * Actual exectution vary for me on every page refresh. > > > I get 5ms for the ad hoc method and 7 for the proto method. > > > 2009/9/3 kangax > > > > On Sep 2, 6:25 pm, joneff wrote: > > > > (It's kinda long and it might be for the other prototype group, but I > > > > am not sure.) > > > > > I was poking around with a script for manipulating tables which takes > > > > heavy use of Element#siblings for some of the manips. > > > > > And I found that in some cases it [the method] tends to be slow. Not > > > > slow like "Vista on a 486 PC" but slow as in "a bit slower than I > > > > expected". > > > > > But then again I am usually testing on 1000 row tables with enough > > > > cols to make FF choke and was like "maybe it's supposed to be like > > > > that. maybe if I use querySelectorAll it will be faster". > > > > > I mean, I do remember an immediate following sibling selector (+) and > > > > all following siblings selector (~). It seemed to me, that there > > > > should be ALL siblings selector. Alas I was wrong. Not to mention it's > > > > kinda wicked to work with qSA. > > > > > So what I did was to dig in prototype code and find the > > > > Element#siblings. I admit it's logic is perfect -- ALL siblings = next > > > > siblings + following siblings. The only thing that bothered me was the > > > > amount of function calls -- I mean this function call that function, > > > > and calls another one, and another one and so on and so forth. > > > > > Note: I am do CSS for a living. Thus I have absolutely no idea how > > > > much time it takes (if any) to jump from a function to function. > > > > > Anyway, I made my way up the function, trying to keep the code general > > > > feeling and I was left with this > > > > > siblngs: function (element) { > > > > if (!element) return []; > > > > element = element.parentNode.firstChild, elements = []; > > > > while (element) { > > > > if (element.nodeType == 1 && element != arguments[0]) > > > elements.push > > > > (Element.extend(element)); > > > > element = element.nextSibling; > > > > } > > > > return elements; > > > > > } > > > > > which, I have to admit wasn't as faster as I expected. > > > > > Anyway, I went over to jQ and mT to see how they do it. > > > > > jQ's approach was more or less similar. It does use this weird for > > > > statement (translated to fit) -- (;element;element.nextSibling) -- > > > > instead of the while, but the I guess that wouldn't make a difference. > > > > > mT was even m
[Prototype-core] Re: Element#siblings
`adHocSiblings` is clearly faster. I guess since it avoids 2 extra function calls (`previousSiblings` and `nextSiblings`). Running a simple test based on your example page: var tdEl = document.getElementsByTagName('td')[100]; var t = new Date(); for (var i=1000; i--; ) protoSiblings(tdEl); var t1 = new Date() - t; t = new Date(); for (var i=1000; i--; ) adHocSiblings(tdEl); var t2 = new Date() - t; t = new Date(); for (var i=1000; i--; ) siblings2(tdEl); var t3 = new Date() - t; document.write( 'protoSiblings: ' + t1 + 'ms;'+ 'adHocSiblings: ' + t2 + 'ms;'+ 'siblings2: ' + t3 + 'ms'); where `siblings2` is practically your `adHocSiblings`, but with few more optimizations (such as do-while instead of while-do, as well as removal of `push` and `arguments`) - function siblings2(element) { if (!element) return []; var originalElement = element, elements = [], i = 0; element = element.parentNode.firstChild; do { if (element.nodeType == 1 && element != originalElement) { elements[i++] = element; } } while (element = element.nextSibling) return elements; } === FF 3.5.2 protoSiblings: 41ms; adHocSiblings: 23ms; siblings2: 19ms === Opera 10 protoSiblings: 78ms; adHocSiblings: 61ms; siblings2: 45ms === Safari 3.2.1 protoSiblings: 28ms; adHocSiblings: 17ms; siblings2: 14ms -- kangax On Sep 3, 5:33 am, Иван Жеков wrote: > Actually I did make a test case > --http://groups.google.com/group/prototype-core/web/element%23siblings.zip-- > zipped to take less space from the quota. > > For fair tests, I extracted the methods as simple functions. > > Note: > * The first click is noticably slower then the rest of the clicks. > * Actual exectution vary for me on every page refresh. > > I get 5ms for the ad hoc method and 7 for the proto method. > > 2009/9/3 kangax > > > > > On Sep 2, 6:25 pm, joneff wrote: > > > (It's kinda long and it might be for the other prototype group, but I > > > am not sure.) > > > > I was poking around with a script for manipulating tables which takes > > > heavy use of Element#siblings for some of the manips. > > > > And I found that in some cases it [the method] tends to be slow. Not > > > slow like "Vista on a 486 PC" but slow as in "a bit slower than I > > > expected". > > > > But then again I am usually testing on 1000 row tables with enough > > > cols to make FF choke and was like "maybe it's supposed to be like > > > that. maybe if I use querySelectorAll it will be faster". > > > > I mean, I do remember an immediate following sibling selector (+) and > > > all following siblings selector (~). It seemed to me, that there > > > should be ALL siblings selector. Alas I was wrong. Not to mention it's > > > kinda wicked to work with qSA. > > > > So what I did was to dig in prototype code and find the > > > Element#siblings. I admit it's logic is perfect -- ALL siblings = next > > > siblings + following siblings. The only thing that bothered me was the > > > amount of function calls -- I mean this function call that function, > > > and calls another one, and another one and so on and so forth. > > > > Note: I am do CSS for a living. Thus I have absolutely no idea how > > > much time it takes (if any) to jump from a function to function. > > > > Anyway, I made my way up the function, trying to keep the code general > > > feeling and I was left with this > > > > siblngs: function (element) { > > > if (!element) return []; > > > element = element.parentNode.firstChild, elements = []; > > > while (element) { > > > if (element.nodeType == 1 && element != arguments[0]) > > elements.push > > > (Element.extend(element)); > > > element = element.nextSibling; > > > } > > > return elements; > > > > } > > > > which, I have to admit wasn't as faster as I expected. > > > > Anyway, I went over to jQ and mT to see how they do it. > > > > jQ's approach was more or less similar. It does use this weird for > > > statement (translated to fit) -- (;element;element.nextSibling) -- > > > instead of the while, but the I guess that wouldn't make a difference. > > > > mT was even more exotic then the original Prototype method, but kinda > > > has the same spirit as the one above. > > > > Sooo... Like I noticed in the beginning, that was long, and I am still > > > not sure it's for this group, and I having in mind I do CSS for a > > > living, I am asking -- is this "improved" Element#siblings faster? > > > Why not make a simple test case to see if it really is faster? > > > -- > > kangax > > --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to prototype-core-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~
[Prototype-core] Re: Element#siblings
Actually I did make a test case -- http://groups.google.com/group/prototype-core/web/element%23siblings.zip -- zipped to take less space from the quota. For fair tests, I extracted the methods as simple functions. Note: * The first click is noticably slower then the rest of the clicks. * Actual exectution vary for me on every page refresh. I get 5ms for the ad hoc method and 7 for the proto method. 2009/9/3 kangax > > On Sep 2, 6:25 pm, joneff wrote: > > (It's kinda long and it might be for the other prototype group, but I > > am not sure.) > > > > I was poking around with a script for manipulating tables which takes > > heavy use of Element#siblings for some of the manips. > > > > And I found that in some cases it [the method] tends to be slow. Not > > slow like "Vista on a 486 PC" but slow as in "a bit slower than I > > expected". > > > > But then again I am usually testing on 1000 row tables with enough > > cols to make FF choke and was like "maybe it's supposed to be like > > that. maybe if I use querySelectorAll it will be faster". > > > > I mean, I do remember an immediate following sibling selector (+) and > > all following siblings selector (~). It seemed to me, that there > > should be ALL siblings selector. Alas I was wrong. Not to mention it's > > kinda wicked to work with qSA. > > > > So what I did was to dig in prototype code and find the > > Element#siblings. I admit it's logic is perfect -- ALL siblings = next > > siblings + following siblings. The only thing that bothered me was the > > amount of function calls -- I mean this function call that function, > > and calls another one, and another one and so on and so forth. > > > > Note: I am do CSS for a living. Thus I have absolutely no idea how > > much time it takes (if any) to jump from a function to function. > > > > Anyway, I made my way up the function, trying to keep the code general > > feeling and I was left with this > > > > siblngs: function (element) { > > if (!element) return []; > > element = element.parentNode.firstChild, elements = []; > > while (element) { > > if (element.nodeType == 1 && element != arguments[0]) > elements.push > > (Element.extend(element)); > > element = element.nextSibling; > > } > > return elements; > > > > } > > > > which, I have to admit wasn't as faster as I expected. > > > > Anyway, I went over to jQ and mT to see how they do it. > > > > jQ's approach was more or less similar. It does use this weird for > > statement (translated to fit) -- (;element;element.nextSibling) -- > > instead of the while, but the I guess that wouldn't make a difference. > > > > mT was even more exotic then the original Prototype method, but kinda > > has the same spirit as the one above. > > > > Sooo... Like I noticed in the beginning, that was long, and I am still > > not sure it's for this group, and I having in mind I do CSS for a > > living, I am asking -- is this "improved" Element#siblings faster? > > Why not make a simple test case to see if it really is faster? > > -- > kangax > > > --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to prototype-core-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Element#siblings
On Sep 2, 6:25 pm, joneff wrote: > (It's kinda long and it might be for the other prototype group, but I > am not sure.) > > I was poking around with a script for manipulating tables which takes > heavy use of Element#siblings for some of the manips. > > And I found that in some cases it [the method] tends to be slow. Not > slow like "Vista on a 486 PC" but slow as in "a bit slower than I > expected". > > But then again I am usually testing on 1000 row tables with enough > cols to make FF choke and was like "maybe it's supposed to be like > that. maybe if I use querySelectorAll it will be faster". > > I mean, I do remember an immediate following sibling selector (+) and > all following siblings selector (~). It seemed to me, that there > should be ALL siblings selector. Alas I was wrong. Not to mention it's > kinda wicked to work with qSA. > > So what I did was to dig in prototype code and find the > Element#siblings. I admit it's logic is perfect -- ALL siblings = next > siblings + following siblings. The only thing that bothered me was the > amount of function calls -- I mean this function call that function, > and calls another one, and another one and so on and so forth. > > Note: I am do CSS for a living. Thus I have absolutely no idea how > much time it takes (if any) to jump from a function to function. > > Anyway, I made my way up the function, trying to keep the code general > feeling and I was left with this > > siblngs: function (element) { > if (!element) return []; > element = element.parentNode.firstChild, elements = []; > while (element) { > if (element.nodeType == 1 && element != arguments[0]) > elements.push > (Element.extend(element)); > element = element.nextSibling; > } > return elements; > > } > > which, I have to admit wasn't as faster as I expected. > > Anyway, I went over to jQ and mT to see how they do it. > > jQ's approach was more or less similar. It does use this weird for > statement (translated to fit) -- (;element;element.nextSibling) -- > instead of the while, but the I guess that wouldn't make a difference. > > mT was even more exotic then the original Prototype method, but kinda > has the same spirit as the one above. > > Sooo... Like I noticed in the beginning, that was long, and I am still > not sure it's for this group, and I having in mind I do CSS for a > living, I am asking -- is this "improved" Element#siblings faster? Why not make a simple test case to see if it really is faster? -- kangax --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to prototype-core-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---