mirror of
https://github.com/PuerkitoBio/goquery.git
synced 2026-10-19 16:15:33 +00:00
perf: walk s.Nodes directly in HasNodes
HasNodes routed through FilterFunction -> winnowFunction -> grep, which allocated a single-node Selection and a closure capture per source element, just to call sel.Contains(n) which is itself a one-iteration sliceContains over the wrapped node. This commit inlines a direct double loop over s.Nodes x nodes calling nodeContains, and push the result via pushStack. name old allocs/op new allocs/op delta Has-8 55.00 ± 0% 24.00 ± 0% -56.36% (p=0.000) HasNodes-8 752.00 ± 0% 4.00 ± 0% -99.47% (p=0.000) HasSelection-8 752.00 ± 0% 3.00 ± 0% -99.60% (p=0.000)
This commit is contained in:
@@ -93,15 +93,16 @@ func (s *Selection) HasMatcher(m Matcher) *Selection {
|
||||
// descendant that matches one of the nodes.
|
||||
// It returns a new Selection object with the matching elements.
|
||||
func (s *Selection) HasNodes(nodes ...*html.Node) *Selection {
|
||||
return s.FilterFunction(func(_ int, sel *Selection) bool {
|
||||
// Add all nodes that contain one of the specified nodes
|
||||
for _, n := range nodes {
|
||||
if sel.Contains(n) {
|
||||
return true
|
||||
var result []*html.Node
|
||||
for _, n := range s.Nodes {
|
||||
for _, candidate := range nodes {
|
||||
if nodeContains(n, candidate) {
|
||||
result = append(result, n)
|
||||
break
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
return pushStack(s, result)
|
||||
}
|
||||
|
||||
// HasSelection reduces the set of matched elements to those that have a
|
||||
|
||||
Reference in New Issue
Block a user