mirror of
https://github.com/PuerkitoBio/goquery.git
synced 2026-10-19 16:15:33 +00:00
perf: presize node-set maps in mapNodes, ClosestNodes and winnowNodes
Three internal helpers build a map[*html.Node]bool from a known set of nodes (or use one as a dedup accumulator over a known number of input nodes) but allocate the map without a size hint. They then incur grow-and-double rehashing as entries are inserted. Pass len(nodes) as the size hint at make time: - traversal.go mapNodes: dedup map shared by appendWithoutDuplicates across every per-node result. mapNodes is the engine behind most traversal helpers (Parents, Children, Next/Prev, Siblings, Find*, Contents, ...), so the impact is broad. - traversal.go ClosestNodes: target-node set built from nodes... - filter.go winnowNodes: large-N path's lookup set built from nodes... Double-digit performance gains across ~all benchmarks.
This commit is contained in:
@@ -149,7 +149,7 @@ func winnowNodes(sel *Selection, nodes []*html.Node, keep bool) []*html.Node {
|
||||
})
|
||||
}
|
||||
|
||||
set := make(map[*html.Node]bool)
|
||||
set := make(map[*html.Node]bool, len(nodes))
|
||||
for _, n := range nodes {
|
||||
set[n] = true
|
||||
}
|
||||
|
||||
+2
-2
@@ -149,7 +149,7 @@ func (s *Selection) ClosestMatcher(m Matcher) *Selection {
|
||||
// ClosestNodes gets the first element that matches one of the nodes by testing the
|
||||
// element itself and traversing up through its ancestors in the DOM tree.
|
||||
func (s *Selection) ClosestNodes(nodes ...*html.Node) *Selection {
|
||||
set := make(map[*html.Node]bool)
|
||||
set := make(map[*html.Node]bool, len(nodes))
|
||||
for _, n := range nodes {
|
||||
set[n] = true
|
||||
}
|
||||
@@ -689,7 +689,7 @@ func getParentNodes(nodes []*html.Node) []*html.Node {
|
||||
// Returns an array of nodes mapped by calling the callback function once for
|
||||
// each node in the source nodes.
|
||||
func mapNodes(nodes []*html.Node, f func(int, *html.Node) []*html.Node) (result []*html.Node) {
|
||||
set := make(map[*html.Node]bool)
|
||||
set := make(map[*html.Node]bool, len(nodes))
|
||||
for i, n := range nodes {
|
||||
if vals := f(i, n); len(vals) > 0 {
|
||||
result = appendWithoutDuplicates(result, vals, set)
|
||||
|
||||
Reference in New Issue
Block a user