perf: skip dedup map in mapNodes for single-node selections

mapNodes always allocated a map[*html.Node]bool for deduplication, even
when called with a single source node where duplicates cannot arise.
Short-circuit to return the callback result directly when len(nodes)==1.
Also add a special case for when there are zero nodes.

This benefits all traversal methods (Find, Children, Parent, Next, Prev,
etc.) when operating on a single-node selection, which is the common
case after First(), Eq(), or directly on a Document.

name      old ns/op   new ns/op   delta
Find-8    23200       14200       -38.8%

name      old B/op    new B/op    delta
Find-8    4632        1496        -67.7%

name      old allocs  new allocs  delta
Find-8    27          13          -51.9%
This commit is contained in:
jvoisin
2026-05-27 21:17:38 +02:00
parent 33466f5bcd
commit 25b585d336
+7
View File
@@ -694,6 +694,13 @@ 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) {
switch len(nodes) {
case 0:
return nil
case 1:
return f(0, nodes[0])
}
set := make(map[*html.Node]bool)
for i, n := range nodes {
if vals := f(i, n); len(vals) > 0 {