Depending on the callback function for uasort(), array_multisort() may be faster.
With this patch the running time of element_children() is reduced by about 50% on an element with 10 children with all different #weights, and about 20% on an element with 10 children of which only one has a #weight specified. With 500 children with all different #weights, the running time is reduced with about 65%. If no child has a #weight specified, the running time is unchanged.
The $i++ / 1000 part is moved from form.inc and helps maintain the order of elements with equal weights. For some reason, adding this fraction actually reduces the running time of array_multisort().
This introduces a small BC break in that array_multisort() does not maintain index association for numeric keys, i.e. children added with $element[] = array(...) rather than $element['foo'] = array(...).
The times have been measured using PHP 5.2.6 on a pretty old/slow machine.
| Comment | File | Size | Author |
|---|---|---|---|
| #6 | drupal-common.inc-639974-D6.patch | 951 bytes | mikeytown2 |
| #2 | ksort-node-add-article.txt | 1.39 KB | casey |
| #2 | multisort-node-add-article.txt | 1.39 KB | casey |
| #2 | head-node-add-article.txt | 1.39 KB | casey |
| #2 | ksort-frontpage.txt | 1.38 KB | casey |
Comments
Comment #1
c960657 commentedComment #2
casey commentedReroll.
I do however hardly get any difference when benchmarking. I also tried another approach, but not much either.
Benchmarks on frontpage were tested with 10 nodes on it.
Comment #3
dave reidI'm doubtful of this as well...
Comment #5
c960657 commentedMy measurements where made using microtime() (not Xdebug profiling) on the function itself. The idea is to save a few calls to is_array()/isset() — O(n) versus O(n × ln n). I guess sorting generally doesn't take much of the total page generation time, except in extreme conditions (large number of elements, n, in each array).
The idea of moving the
$i++ / 1000to element_children() still applies, though. Currently only forms preserve the original order. The following will output “BA AB” (and some non-visible markup):Comment #6
mikeytown2 commentedI see that element_children is a lot different between 6.x & 7.x; but this patch is along the similar goals - speed up element_children(); only its for 6.x. Using this you can knock off about hundred milliseconds from the page render time, if the page has a lot on it.
Let me know if this should go in a new issue or stay here.
Comment #7
catchI profilied the node/add/article page with the original patch and ended up with more calls to is_array() with the patch than without (and no less calls to anything else). No overall difference in performance, 0.1% at most, this is from 120+ calls to element_children() on that page.
array_multisort() compared to uasort() is a lot cheaper looking at the profile data, but that only gets called 9 times on the node form, so no wonder it doesn't make much difference. If there's a better form to test on - maybe modules page or permissions? That might help to compare better.
Comment #8
c960657 commentedI cannot reproduce that. With the patch I see a reduction in the number of calls to is_array() as well as to element_sort():
The difference between O(n) and O(n × ln n only really gets visible for large values of n, i.e. when the array to be sorted contains a lot of elements, and probably only when the elements are not already almost sorted. I'm not sure where to find a good example in core - most forms are divided into separate fieldsets, and most lists are already sorted.
Comment #9
sunThis needs to stay here, because form elements may be expanded into sub-elements. Therefore, an element may have certain child elements already, but further children are added later in the process. Since the default order of array keys in PHP is derived from their definition order, removing this preemptive #weight will lead to wrongly ordered elements everywhere.
However, aside from that, this array_multisort() approach makes much more sense to me than the other element_sort() performance patch.
Powered by Dreditor.
Comment #10
gielfeldt commentedsubscribe
Comment #11
bfroehle commentedPlease be aware that array_multisort can cause warnings if some child elements are not arrays -- see #972536-35: Object of class stdClass could not be converted to int in _menu_router_build() - line 3370 for a complete description.
Comment #12
DanPir commentedsubscribe
Comment #13
rjbrown99 commentedDuplicate of #1345204: Optimize element_children()? There is another patch there for this same general concept.
Comment #14
mikeytown2 commented@rjbrown99
I split the D6 patch (#6) off from this thread as the functions are quite different in D6 vs D7. Similar goals, different code.