mirror of
https://github.com/PuerkitoBio/goquery.git
synced 2026-10-19 16:15:33 +00:00
perf: short-circuit IsMatcher on the first match
IsMatcher handled multi-node selections by calling m.Filter(s.Nodes) and checking whether the returned slice was non-empty, forcing the matcher to walk the whole selection and materialize all matches even though the API only needs an existence check. This commit replaces this with a simple loop over s.Nodes that calls m.Match(n) and returns true on the first match. This also makes the single-node special case unnecessary. Benchmark results on arm64 over 10 runs: name old time/op new time/op delta Is-8 4.67µs 1.32µs -71.7% IsPositional-8 21.44µs 0.82µs -96.2% name old B/op new B/op delta Is-8 96 80 -16.7% IsPositional-8 1144 184 -83.9% name old allocs new allocs delta Is-8 5 4 -20.0% IsPositional-8 11 7 -36.4%
This commit is contained in:
@@ -11,13 +11,11 @@ func (s *Selection) Is(selector string) bool {
|
||||
// IsMatcher checks the current matched set of elements against a matcher and
|
||||
// returns true if at least one of these elements matches.
|
||||
func (s *Selection) IsMatcher(m Matcher) bool {
|
||||
if len(s.Nodes) > 0 {
|
||||
if len(s.Nodes) == 1 {
|
||||
return m.Match(s.Nodes[0])
|
||||
for _, n := range s.Nodes {
|
||||
if m.Match(n) {
|
||||
return true
|
||||
}
|
||||
return len(m.Filter(s.Nodes)) > 0
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user