mirror of
https://github.com/PuerkitoBio/goquery.git
synced 2026-10-19 16:15:33 +00:00
perf: drop grep/closure indirection in winnowNodes
In the same spirit as #545, replaces costly grep() with a loop. While escape analysis managed to stack-allocate the per-node Selection through grep's inlining, the closure capture itself (nodes and keep) was still heap-allocated. Local benchmarks are showing a 30% allocs/op reduction, and a ~10-20% reduction in sec/op.
This commit is contained in:
@@ -144,18 +144,26 @@ func winnow(sel *Selection, m Matcher, keep bool) []*html.Node {
|
||||
// to get rid of (Not) the matching elements.
|
||||
func winnowNodes(sel *Selection, nodes []*html.Node, keep bool) []*html.Node {
|
||||
if len(nodes)+len(sel.Nodes) < minNodesForSet {
|
||||
return grep(sel, func(i int, s *Selection) bool {
|
||||
return isInSlice(nodes, s.Get(0)) == keep
|
||||
})
|
||||
var result []*html.Node
|
||||
for _, n := range sel.Nodes {
|
||||
if isInSlice(nodes, n) == keep {
|
||||
result = append(result, n)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
set := make(map[*html.Node]bool)
|
||||
for _, n := range nodes {
|
||||
set[n] = true
|
||||
}
|
||||
return grep(sel, func(i int, s *Selection) bool {
|
||||
return set[s.Get(0)] == keep
|
||||
})
|
||||
var result []*html.Node
|
||||
for _, n := range sel.Nodes {
|
||||
if set[n] == keep {
|
||||
result = append(result, n)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Filter based on a function test, and the indicator to keep (Filter) or
|
||||
|
||||
Reference in New Issue
Block a user