Compare commits

..
Author SHA1 Message Date
Martin Angers 5dccaa115b optimize winnowNodes and ClosestNodes in the same way 2016-08-28 11:55:36 -04:00
Martin Angers 26f4f54c91 simplify string search expressions, remove unused code 2016-08-28 11:09:29 -04:00
Martin Angers e89fe653fd update README for v1.0.1 2016-08-28 11:06:06 -04:00
Martin Angers ab2bb46123 update pre-commit hook with other static checks 2016-08-28 11:04:26 -04:00
Martin Angers b91267330e add tests and benchmark for appendWithoutDuplicates optimization 2016-08-28 11:03:18 -04:00
Martin Angers d85ad7e2ed remove var declaration 2016-08-27 22:44:10 -04:00
Martin Angers 6841d28c6f comment and explain the appendWithoutDuplicates logic 2016-08-27 22:29:53 -04:00
Martin Angers 7bd630023a reuse the deduplication set map in mapNodes 2016-08-27 22:25:02 -04:00
Martin Angers c7533ba696 maintain a set of existing target nodes to deduplicate
The old implementation used nested loops to check if one of the
new nodes was already in the existing nodes. This commit
maintains a map[*html.Node]bool so that a single loop over
the new elements is required. This is slower for small
slices though, and allocates more. The next step is for
appendWithoutDuplicates to accept a map as argument so
that the set is not recreated on each call from mapNodes.
2016-08-27 18:55:21 -04:00
Martin Angers ad8b3d8222 remove logging from benchmarks, validate expected result instead 2016-08-27 18:37:55 -04:00
23 changed files with 729 additions and 145 deletions
+10 -1
View File
@@ -1,7 +1,16 @@
# editor temporary files
*.sublime-*
.DS_Store
*.swp
#*.*#
tags
goquery.test
# direnv config
.env*
# test binaries
*.test
# coverage and profilte outputs
*.out
+1
View File
@@ -26,6 +26,7 @@ Please note that because of the net/html dependency, goquery requires Go1.1+.
**Note that goquery's API is now stable, and will not break.**
* **2016-08-28 (v1.0.1)** : Optimize performance for large documents.
* **2016-07-27 (v1.0.0)** : Tag version 1.0.0.
* **2016-06-15** : Invalid selector strings internally compile to a `Matcher` implementation that never matches any node (instead of a panic). So for example, `doc.Find("~")` returns an empty `*Selection` object.
* **2016-02-02** : Add `NodeName` utility function similar to the DOM's `nodeName` property. It returns the tag name of the first element in a selection, and other relevant values of non-element nodes (see godoc for details). Add `OuterHtml` utility function similar to the DOM's `outerHTML` property (named `OuterHtml` in small caps for consistency with the existing `Html` method on the `Selection`).
+85
View File
@@ -0,0 +1,85 @@
BenchmarkFirst-4 30000000 50.7 ns/op 48 B/op 1 allocs/op
BenchmarkLast-4 30000000 50.9 ns/op 48 B/op 1 allocs/op
BenchmarkEq-4 30000000 55.7 ns/op 48 B/op 1 allocs/op
BenchmarkSlice-4 500000000 3.45 ns/op 0 B/op 0 allocs/op
BenchmarkGet-4 2000000000 1.68 ns/op 0 B/op 0 allocs/op
BenchmarkIndex-4 3000000 541 ns/op 248 B/op 10 allocs/op
BenchmarkIndexSelector-4 200000 10749 ns/op 2464 B/op 17 allocs/op
BenchmarkIndexOfNode-4 200000000 6.47 ns/op 0 B/op 0 allocs/op
BenchmarkIndexOfSelection-4 200000000 7.27 ns/op 0 B/op 0 allocs/op
BenchmarkMetalReviewExample-4 10000 138426 ns/op 12240 B/op 319 allocs/op
BenchmarkAdd-4 200000 10192 ns/op 208 B/op 9 allocs/op
BenchmarkAddSelection-4 10000000 158 ns/op 48 B/op 1 allocs/op
BenchmarkAddNodes-4 10000000 156 ns/op 48 B/op 1 allocs/op
BenchmarkAndSelf-4 1000000 1588 ns/op 1008 B/op 5 allocs/op
BenchmarkFilter-4 100000 20427 ns/op 360 B/op 8 allocs/op
BenchmarkNot-4 100000 23508 ns/op 136 B/op 5 allocs/op
BenchmarkFilterFunction-4 50000 34178 ns/op 22976 B/op 755 allocs/op
BenchmarkNotFunction-4 50000 38173 ns/op 29120 B/op 757 allocs/op
BenchmarkFilterNodes-4 50000 34001 ns/op 20960 B/op 749 allocs/op
BenchmarkNotNodes-4 30000 40344 ns/op 29120 B/op 757 allocs/op
BenchmarkFilterSelection-4 50000 33308 ns/op 20960 B/op 749 allocs/op
BenchmarkNotSelection-4 30000 40748 ns/op 29120 B/op 757 allocs/op
BenchmarkHas-4 5000 263346 ns/op 1816 B/op 48 allocs/op
BenchmarkHasNodes-4 10000 160840 ns/op 21184 B/op 752 allocs/op
BenchmarkHasSelection-4 10000 165410 ns/op 21184 B/op 752 allocs/op
BenchmarkEnd-4 2000000000 1.01 ns/op 0 B/op 0 allocs/op
BenchmarkEach-4 300000 4664 ns/op 3304 B/op 118 allocs/op
BenchmarkMap-4 200000 8286 ns/op 5572 B/op 184 allocs/op
BenchmarkEachWithBreak-4 2000000 806 ns/op 560 B/op 20 allocs/op
BenchmarkAttr-4 100000000 21.6 ns/op 0 B/op 0 allocs/op
BenchmarkText-4 200000 8909 ns/op 7536 B/op 110 allocs/op
BenchmarkLength-4 2000000000 0.34 ns/op 0 B/op 0 allocs/op
BenchmarkHtml-4 3000000 422 ns/op 120 B/op 2 allocs/op
BenchmarkIs-4 100000 22615 ns/op 88 B/op 4 allocs/op
BenchmarkIsPositional-4 50000 26655 ns/op 1112 B/op 10 allocs/op
BenchmarkIsFunction-4 1000000 1208 ns/op 784 B/op 28 allocs/op
BenchmarkIsSelection-4 50000 33497 ns/op 20960 B/op 749 allocs/op
BenchmarkIsNodes-4 50000 33572 ns/op 20960 B/op 749 allocs/op
BenchmarkHasClass-4 10000 232802 ns/op 14944 B/op 976 allocs/op
BenchmarkContains-4 200000000 7.33 ns/op 0 B/op 0 allocs/op
BenchmarkFind-4 200000 10715 ns/op 2464 B/op 17 allocs/op
BenchmarkFindWithinSelection-4 50000 35878 ns/op 2176 B/op 78 allocs/op
BenchmarkFindSelection-4 10000 194356 ns/op 2672 B/op 82 allocs/op
BenchmarkFindNodes-4 10000 195510 ns/op 2672 B/op 82 allocs/op
BenchmarkContents-4 1000000 2252 ns/op 864 B/op 34 allocs/op
BenchmarkContentsFiltered-4 500000 3015 ns/op 1016 B/op 39 allocs/op
BenchmarkChildren-4 5000000 364 ns/op 152 B/op 7 allocs/op
BenchmarkChildrenFiltered-4 1000000 2212 ns/op 352 B/op 15 allocs/op
BenchmarkParent-4 50000 24643 ns/op 4048 B/op 381 allocs/op
BenchmarkParentFiltered-4 50000 25967 ns/op 4248 B/op 388 allocs/op
BenchmarkParents-4 30000 50000 ns/op 27776 B/op 830 allocs/op
BenchmarkParentsFiltered-4 30000 53107 ns/op 28360 B/op 838 allocs/op
BenchmarkParentsUntil-4 100000 22423 ns/op 10352 B/op 353 allocs/op
BenchmarkParentsUntilSelection-4 20000 86925 ns/op 51144 B/op 1516 allocs/op
BenchmarkParentsUntilNodes-4 20000 87597 ns/op 51144 B/op 1516 allocs/op
BenchmarkParentsFilteredUntil-4 300000 5568 ns/op 2232 B/op 86 allocs/op
BenchmarkParentsFilteredUntilSelection-4 200000 10966 ns/op 5440 B/op 190 allocs/op
BenchmarkParentsFilteredUntilNodes-4 200000 10919 ns/op 5440 B/op 190 allocs/op
BenchmarkSiblings-4 30000 46018 ns/op 15400 B/op 204 allocs/op
BenchmarkSiblingsFiltered-4 30000 50566 ns/op 16496 B/op 213 allocs/op
BenchmarkNext-4 200000 7921 ns/op 3216 B/op 112 allocs/op
BenchmarkNextFiltered-4 200000 8804 ns/op 3416 B/op 118 allocs/op
BenchmarkNextAll-4 50000 31098 ns/op 9912 B/op 138 allocs/op
BenchmarkNextAllFiltered-4 50000 34677 ns/op 11008 B/op 147 allocs/op
BenchmarkPrev-4 200000 7920 ns/op 3216 B/op 112 allocs/op
BenchmarkPrevFiltered-4 200000 8913 ns/op 3416 B/op 118 allocs/op
BenchmarkPrevAll-4 200000 10845 ns/op 4376 B/op 113 allocs/op
BenchmarkPrevAllFiltered-4 100000 12030 ns/op 4576 B/op 119 allocs/op
BenchmarkNextUntil-4 100000 19193 ns/op 5760 B/op 260 allocs/op
BenchmarkNextUntilSelection-4 50000 34829 ns/op 18480 B/op 542 allocs/op
BenchmarkNextUntilNodes-4 100000 14459 ns/op 7944 B/op 248 allocs/op
BenchmarkPrevUntil-4 20000 66296 ns/op 12856 B/op 448 allocs/op
BenchmarkPrevUntilSelection-4 30000 45037 ns/op 23432 B/op 689 allocs/op
BenchmarkPrevUntilNodes-4 200000 11525 ns/op 6152 B/op 203 allocs/op
BenchmarkNextFilteredUntil-4 100000 12940 ns/op 4512 B/op 173 allocs/op
BenchmarkNextFilteredUntilSelection-4 50000 38924 ns/op 19160 B/op 567 allocs/op
BenchmarkNextFilteredUntilNodes-4 50000 38528 ns/op 19160 B/op 567 allocs/op
BenchmarkPrevFilteredUntil-4 100000 12980 ns/op 4664 B/op 175 allocs/op
BenchmarkPrevFilteredUntilSelection-4 50000 39671 ns/op 19936 B/op 587 allocs/op
BenchmarkPrevFilteredUntilNodes-4 50000 39484 ns/op 19936 B/op 587 allocs/op
BenchmarkClosest-4 500000 3310 ns/op 160 B/op 8 allocs/op
BenchmarkClosestSelection-4 5000000 361 ns/op 96 B/op 6 allocs/op
BenchmarkClosestNodes-4 5000000 359 ns/op 96 B/op 6 allocs/op
PASS
ok github.com/PuerkitoBio/goquery 163.718s
+85
View File
@@ -0,0 +1,85 @@
BenchmarkFirst-4 30000000 50.9 ns/op 48 B/op 1 allocs/op
BenchmarkLast-4 30000000 50.0 ns/op 48 B/op 1 allocs/op
BenchmarkEq-4 30000000 50.5 ns/op 48 B/op 1 allocs/op
BenchmarkSlice-4 500000000 3.53 ns/op 0 B/op 0 allocs/op
BenchmarkGet-4 2000000000 1.66 ns/op 0 B/op 0 allocs/op
BenchmarkIndex-4 2000000 832 ns/op 248 B/op 10 allocs/op
BenchmarkIndexSelector-4 100000 16073 ns/op 3839 B/op 21 allocs/op
BenchmarkIndexOfNode-4 200000000 6.38 ns/op 0 B/op 0 allocs/op
BenchmarkIndexOfSelection-4 200000000 7.14 ns/op 0 B/op 0 allocs/op
BenchmarkMetalReviewExample-4 10000 140737 ns/op 12418 B/op 320 allocs/op
BenchmarkAdd-4 100000 13162 ns/op 974 B/op 10 allocs/op
BenchmarkAddSelection-4 500000 3160 ns/op 814 B/op 2 allocs/op
BenchmarkAddNodes-4 500000 3159 ns/op 814 B/op 2 allocs/op
BenchmarkAndSelf-4 200000 7423 ns/op 2404 B/op 9 allocs/op
BenchmarkFilter-4 100000 19671 ns/op 360 B/op 8 allocs/op
BenchmarkNot-4 100000 22577 ns/op 136 B/op 5 allocs/op
BenchmarkFilterFunction-4 50000 33960 ns/op 22976 B/op 755 allocs/op
BenchmarkNotFunction-4 50000 37909 ns/op 29120 B/op 757 allocs/op
BenchmarkFilterNodes-4 50000 34196 ns/op 20960 B/op 749 allocs/op
BenchmarkNotNodes-4 30000 40446 ns/op 29120 B/op 757 allocs/op
BenchmarkFilterSelection-4 50000 33091 ns/op 20960 B/op 749 allocs/op
BenchmarkNotSelection-4 30000 40609 ns/op 29120 B/op 757 allocs/op
BenchmarkHas-4 5000 262936 ns/op 2371 B/op 50 allocs/op
BenchmarkHasNodes-4 10000 148631 ns/op 21184 B/op 752 allocs/op
BenchmarkHasSelection-4 10000 153117 ns/op 21184 B/op 752 allocs/op
BenchmarkEnd-4 2000000000 1.02 ns/op 0 B/op 0 allocs/op
BenchmarkEach-4 300000 4653 ns/op 3304 B/op 118 allocs/op
BenchmarkMap-4 200000 8257 ns/op 5572 B/op 184 allocs/op
BenchmarkEachWithBreak-4 2000000 806 ns/op 560 B/op 20 allocs/op
BenchmarkAttr-4 100000000 22.0 ns/op 0 B/op 0 allocs/op
BenchmarkText-4 200000 8913 ns/op 7536 B/op 110 allocs/op
BenchmarkLength-4 2000000000 0.35 ns/op 0 B/op 0 allocs/op
BenchmarkHtml-4 5000000 398 ns/op 120 B/op 2 allocs/op
BenchmarkIs-4 100000 22392 ns/op 88 B/op 4 allocs/op
BenchmarkIsPositional-4 50000 26259 ns/op 1112 B/op 10 allocs/op
BenchmarkIsFunction-4 1000000 1212 ns/op 784 B/op 28 allocs/op
BenchmarkIsSelection-4 50000 33222 ns/op 20960 B/op 749 allocs/op
BenchmarkIsNodes-4 50000 33408 ns/op 20960 B/op 749 allocs/op
BenchmarkHasClass-4 10000 233208 ns/op 14944 B/op 976 allocs/op
BenchmarkContains-4 200000000 7.57 ns/op 0 B/op 0 allocs/op
BenchmarkFind-4 100000 16121 ns/op 3839 B/op 21 allocs/op
BenchmarkFindWithinSelection-4 20000 68019 ns/op 11521 B/op 97 allocs/op
BenchmarkFindSelection-4 5000 387582 ns/op 59787 B/op 176 allocs/op
BenchmarkFindNodes-4 5000 389246 ns/op 59797 B/op 176 allocs/op
BenchmarkContents-4 200000 11475 ns/op 2878 B/op 42 allocs/op
BenchmarkContentsFiltered-4 200000 11222 ns/op 2498 B/op 46 allocs/op
BenchmarkChildren-4 2000000 650 ns/op 152 B/op 7 allocs/op
BenchmarkChildrenFiltered-4 500000 2568 ns/op 352 B/op 15 allocs/op
BenchmarkParent-4 2000 702513 ns/op 194478 B/op 828 allocs/op
BenchmarkParentFiltered-4 2000 690778 ns/op 194658 B/op 835 allocs/op
BenchmarkParents-4 10000 124855 ns/op 49869 B/op 868 allocs/op
BenchmarkParentsFiltered-4 10000 128535 ns/op 50456 B/op 876 allocs/op
BenchmarkParentsUntil-4 20000 72982 ns/op 23802 B/op 388 allocs/op
BenchmarkParentsUntilSelection-4 10000 156099 ns/op 72453 B/op 1549 allocs/op
BenchmarkParentsUntilNodes-4 10000 156610 ns/op 72455 B/op 1549 allocs/op
BenchmarkParentsFilteredUntil-4 100000 15549 ns/op 4068 B/op 94 allocs/op
BenchmarkParentsFilteredUntilSelection-4 100000 20564 ns/op 7276 B/op 198 allocs/op
BenchmarkParentsFilteredUntilNodes-4 100000 20635 ns/op 7276 B/op 198 allocs/op
BenchmarkSiblings-4 3000 565114 ns/op 205910 B/op 336 allocs/op
BenchmarkSiblingsFiltered-4 3000 580264 ns/op 206993 B/op 345 allocs/op
BenchmarkNext-4 20000 93177 ns/op 26810 B/op 169 allocs/op
BenchmarkNextFiltered-4 20000 94171 ns/op 27013 B/op 175 allocs/op
BenchmarkNextAll-4 5000 270320 ns/op 89289 B/op 237 allocs/op
BenchmarkNextAllFiltered-4 5000 275283 ns/op 90375 B/op 246 allocs/op
BenchmarkPrev-4 20000 92777 ns/op 26810 B/op 169 allocs/op
BenchmarkPrevFiltered-4 20000 95577 ns/op 27007 B/op 175 allocs/op
BenchmarkPrevAll-4 20000 86339 ns/op 27515 B/op 151 allocs/op
BenchmarkPrevAllFiltered-4 20000 87759 ns/op 27715 B/op 157 allocs/op
BenchmarkNextUntil-4 10000 163930 ns/op 48541 B/op 330 allocs/op
BenchmarkNextUntilSelection-4 30000 56382 ns/op 23880 B/op 556 allocs/op
BenchmarkNextUntilNodes-4 100000 18883 ns/op 8703 B/op 252 allocs/op
BenchmarkPrevUntil-4 3000 484668 ns/op 145402 B/op 611 allocs/op
BenchmarkPrevUntilSelection-4 20000 72125 ns/op 28865 B/op 705 allocs/op
BenchmarkPrevUntilNodes-4 100000 14722 ns/op 6510 B/op 205 allocs/op
BenchmarkNextFilteredUntil-4 50000 39006 ns/op 10990 B/op 192 allocs/op
BenchmarkNextFilteredUntilSelection-4 20000 66048 ns/op 25641 B/op 586 allocs/op
BenchmarkNextFilteredUntilNodes-4 20000 65314 ns/op 25640 B/op 586 allocs/op
BenchmarkPrevFilteredUntil-4 50000 33312 ns/op 9709 B/op 189 allocs/op
BenchmarkPrevFilteredUntilSelection-4 20000 64197 ns/op 24981 B/op 601 allocs/op
BenchmarkPrevFilteredUntilNodes-4 20000 64505 ns/op 24982 B/op 601 allocs/op
BenchmarkClosest-4 500000 4065 ns/op 160 B/op 8 allocs/op
BenchmarkClosestSelection-4 2000000 756 ns/op 96 B/op 6 allocs/op
BenchmarkClosestNodes-4 2000000 753 ns/op 96 B/op 6 allocs/op
PASS
ok github.com/PuerkitoBio/goquery 162.053s
+85
View File
@@ -0,0 +1,85 @@
BenchmarkFirst-4 30000000 51.8 ns/op 48 B/op 1 allocs/op
BenchmarkLast-4 30000000 50.1 ns/op 48 B/op 1 allocs/op
BenchmarkEq-4 30000000 51.4 ns/op 48 B/op 1 allocs/op
BenchmarkSlice-4 500000000 3.52 ns/op 0 B/op 0 allocs/op
BenchmarkGet-4 2000000000 1.65 ns/op 0 B/op 0 allocs/op
BenchmarkIndex-4 2000000 787 ns/op 248 B/op 10 allocs/op
BenchmarkIndexSelector-4 100000 16952 ns/op 3839 B/op 21 allocs/op
BenchmarkIndexOfNode-4 200000000 6.42 ns/op 0 B/op 0 allocs/op
BenchmarkIndexOfSelection-4 200000000 7.12 ns/op 0 B/op 0 allocs/op
BenchmarkMetalReviewExample-4 10000 141994 ns/op 12418 B/op 320 allocs/op
BenchmarkAdd-4 200000 10367 ns/op 208 B/op 9 allocs/op
BenchmarkAddSelection-4 10000000 152 ns/op 48 B/op 1 allocs/op
BenchmarkAddNodes-4 10000000 147 ns/op 48 B/op 1 allocs/op
BenchmarkAndSelf-4 1000000 1647 ns/op 1008 B/op 5 allocs/op
BenchmarkFilter-4 100000 19522 ns/op 360 B/op 8 allocs/op
BenchmarkNot-4 100000 22546 ns/op 136 B/op 5 allocs/op
BenchmarkFilterFunction-4 50000 35087 ns/op 22976 B/op 755 allocs/op
BenchmarkNotFunction-4 50000 39123 ns/op 29120 B/op 757 allocs/op
BenchmarkFilterNodes-4 50000 34890 ns/op 20960 B/op 749 allocs/op
BenchmarkNotNodes-4 30000 41145 ns/op 29120 B/op 757 allocs/op
BenchmarkFilterSelection-4 50000 33735 ns/op 20960 B/op 749 allocs/op
BenchmarkNotSelection-4 30000 41334 ns/op 29120 B/op 757 allocs/op
BenchmarkHas-4 5000 264058 ns/op 2370 B/op 50 allocs/op
BenchmarkHasNodes-4 10000 151718 ns/op 21184 B/op 752 allocs/op
BenchmarkHasSelection-4 10000 156955 ns/op 21184 B/op 752 allocs/op
BenchmarkEnd-4 2000000000 1.01 ns/op 0 B/op 0 allocs/op
BenchmarkEach-4 300000 4660 ns/op 3304 B/op 118 allocs/op
BenchmarkMap-4 200000 8404 ns/op 5572 B/op 184 allocs/op
BenchmarkEachWithBreak-4 2000000 806 ns/op 560 B/op 20 allocs/op
BenchmarkAttr-4 100000000 21.6 ns/op 0 B/op 0 allocs/op
BenchmarkText-4 200000 8911 ns/op 7536 B/op 110 allocs/op
BenchmarkLength-4 2000000000 0.34 ns/op 0 B/op 0 allocs/op
BenchmarkHtml-4 3000000 405 ns/op 120 B/op 2 allocs/op
BenchmarkIs-4 100000 22228 ns/op 88 B/op 4 allocs/op
BenchmarkIsPositional-4 50000 26469 ns/op 1112 B/op 10 allocs/op
BenchmarkIsFunction-4 1000000 1240 ns/op 784 B/op 28 allocs/op
BenchmarkIsSelection-4 50000 33709 ns/op 20960 B/op 749 allocs/op
BenchmarkIsNodes-4 50000 33711 ns/op 20960 B/op 749 allocs/op
BenchmarkHasClass-4 10000 236005 ns/op 14944 B/op 976 allocs/op
BenchmarkContains-4 200000000 7.47 ns/op 0 B/op 0 allocs/op
BenchmarkFind-4 100000 16075 ns/op 3839 B/op 21 allocs/op
BenchmarkFindWithinSelection-4 30000 41418 ns/op 3539 B/op 82 allocs/op
BenchmarkFindSelection-4 10000 209490 ns/op 5616 B/op 89 allocs/op
BenchmarkFindNodes-4 10000 208206 ns/op 5614 B/op 89 allocs/op
BenchmarkContents-4 300000 4751 ns/op 1420 B/op 36 allocs/op
BenchmarkContentsFiltered-4 300000 5454 ns/op 1570 B/op 41 allocs/op
BenchmarkChildren-4 3000000 527 ns/op 152 B/op 7 allocs/op
BenchmarkChildrenFiltered-4 1000000 2484 ns/op 352 B/op 15 allocs/op
BenchmarkParent-4 50000 34724 ns/op 6940 B/op 387 allocs/op
BenchmarkParentFiltered-4 50000 35596 ns/op 7141 B/op 394 allocs/op
BenchmarkParents-4 20000 62094 ns/op 30720 B/op 837 allocs/op
BenchmarkParentsFiltered-4 20000 63223 ns/op 31304 B/op 845 allocs/op
BenchmarkParentsUntil-4 50000 30391 ns/op 11828 B/op 358 allocs/op
BenchmarkParentsUntilSelection-4 20000 99962 ns/op 54075 B/op 1523 allocs/op
BenchmarkParentsUntilNodes-4 20000 98763 ns/op 54073 B/op 1523 allocs/op
BenchmarkParentsFilteredUntil-4 200000 7982 ns/op 2787 B/op 88 allocs/op
BenchmarkParentsFilteredUntilSelection-4 100000 13618 ns/op 5995 B/op 192 allocs/op
BenchmarkParentsFilteredUntilNodes-4 100000 13639 ns/op 5994 B/op 192 allocs/op
BenchmarkSiblings-4 20000 75287 ns/op 28453 B/op 225 allocs/op
BenchmarkSiblingsFiltered-4 20000 80139 ns/op 29543 B/op 234 allocs/op
BenchmarkNext-4 100000 14270 ns/op 4659 B/op 117 allocs/op
BenchmarkNextFiltered-4 100000 15352 ns/op 4860 B/op 123 allocs/op
BenchmarkNextAll-4 20000 60811 ns/op 22771 B/op 157 allocs/op
BenchmarkNextAllFiltered-4 20000 69079 ns/op 23871 B/op 166 allocs/op
BenchmarkPrev-4 100000 14417 ns/op 4659 B/op 117 allocs/op
BenchmarkPrevFiltered-4 100000 15443 ns/op 4859 B/op 123 allocs/op
BenchmarkPrevAll-4 100000 22008 ns/op 7346 B/op 120 allocs/op
BenchmarkPrevAllFiltered-4 100000 23212 ns/op 7544 B/op 126 allocs/op
BenchmarkNextUntil-4 50000 30589 ns/op 8767 B/op 267 allocs/op
BenchmarkNextUntilSelection-4 30000 40875 ns/op 19862 B/op 546 allocs/op
BenchmarkNextUntilNodes-4 100000 15987 ns/op 8134 B/op 249 allocs/op
BenchmarkPrevUntil-4 20000 98799 ns/op 25727 B/op 467 allocs/op
BenchmarkPrevUntilSelection-4 30000 51874 ns/op 24875 B/op 694 allocs/op
BenchmarkPrevUntilNodes-4 100000 12901 ns/op 6334 B/op 204 allocs/op
BenchmarkNextFilteredUntil-4 100000 19869 ns/op 5909 B/op 177 allocs/op
BenchmarkNextFilteredUntilSelection-4 30000 45412 ns/op 20557 B/op 571 allocs/op
BenchmarkNextFilteredUntilNodes-4 30000 45363 ns/op 20557 B/op 571 allocs/op
BenchmarkPrevFilteredUntil-4 100000 19357 ns/op 6033 B/op 179 allocs/op
BenchmarkPrevFilteredUntilSelection-4 30000 46396 ns/op 21305 B/op 591 allocs/op
BenchmarkPrevFilteredUntilNodes-4 30000 46133 ns/op 21305 B/op 591 allocs/op
BenchmarkClosest-4 500000 3448 ns/op 160 B/op 8 allocs/op
BenchmarkClosestSelection-4 3000000 528 ns/op 96 B/op 6 allocs/op
BenchmarkClosestNodes-4 3000000 523 ns/op 96 B/op 6 allocs/op
PASS
ok github.com/PuerkitoBio/goquery 162.012s
+86
View File
@@ -0,0 +1,86 @@
BenchmarkFirst-4 30000000 51.7 ns/op 48 B/op 1 allocs/op
BenchmarkLast-4 30000000 51.9 ns/op 48 B/op 1 allocs/op
BenchmarkEq-4 30000000 50.0 ns/op 48 B/op 1 allocs/op
BenchmarkSlice-4 500000000 3.47 ns/op 0 B/op 0 allocs/op
BenchmarkGet-4 2000000000 1.68 ns/op 0 B/op 0 allocs/op
BenchmarkIndex-4 2000000 804 ns/op 248 B/op 10 allocs/op
BenchmarkIndexSelector-4 100000 16285 ns/op 3839 B/op 21 allocs/op
BenchmarkIndexOfNode-4 200000000 6.50 ns/op 0 B/op 0 allocs/op
BenchmarkIndexOfSelection-4 200000000 7.02 ns/op 0 B/op 0 allocs/op
BenchmarkMetalReviewExample-4 10000 143160 ns/op 12417 B/op 320 allocs/op
BenchmarkAdd-4 200000 10326 ns/op 208 B/op 9 allocs/op
BenchmarkAddSelection-4 10000000 155 ns/op 48 B/op 1 allocs/op
BenchmarkAddNodes-4 10000000 156 ns/op 48 B/op 1 allocs/op
BenchmarkAddNodesBig-4 20000 94439 ns/op 21847 B/op 37 allocs/op
BenchmarkAndSelf-4 1000000 1791 ns/op 1008 B/op 5 allocs/op
BenchmarkFilter-4 100000 19470 ns/op 360 B/op 8 allocs/op
BenchmarkNot-4 100000 22500 ns/op 136 B/op 5 allocs/op
BenchmarkFilterFunction-4 50000 34578 ns/op 22976 B/op 755 allocs/op
BenchmarkNotFunction-4 50000 38703 ns/op 29120 B/op 757 allocs/op
BenchmarkFilterNodes-4 50000 34486 ns/op 20960 B/op 749 allocs/op
BenchmarkNotNodes-4 30000 41094 ns/op 29120 B/op 757 allocs/op
BenchmarkFilterSelection-4 50000 33623 ns/op 20960 B/op 749 allocs/op
BenchmarkNotSelection-4 30000 41483 ns/op 29120 B/op 757 allocs/op
BenchmarkHas-4 5000 266628 ns/op 2371 B/op 50 allocs/op
BenchmarkHasNodes-4 10000 152617 ns/op 21184 B/op 752 allocs/op
BenchmarkHasSelection-4 10000 156682 ns/op 21184 B/op 752 allocs/op
BenchmarkEnd-4 2000000000 1.00 ns/op 0 B/op 0 allocs/op
BenchmarkEach-4 300000 4712 ns/op 3304 B/op 118 allocs/op
BenchmarkMap-4 200000 8434 ns/op 5572 B/op 184 allocs/op
BenchmarkEachWithBreak-4 2000000 819 ns/op 560 B/op 20 allocs/op
BenchmarkAttr-4 100000000 21.7 ns/op 0 B/op 0 allocs/op
BenchmarkText-4 200000 9376 ns/op 7536 B/op 110 allocs/op
BenchmarkLength-4 2000000000 0.35 ns/op 0 B/op 0 allocs/op
BenchmarkHtml-4 5000000 401 ns/op 120 B/op 2 allocs/op
BenchmarkIs-4 100000 22214 ns/op 88 B/op 4 allocs/op
BenchmarkIsPositional-4 50000 26559 ns/op 1112 B/op 10 allocs/op
BenchmarkIsFunction-4 1000000 1228 ns/op 784 B/op 28 allocs/op
BenchmarkIsSelection-4 50000 33471 ns/op 20960 B/op 749 allocs/op
BenchmarkIsNodes-4 50000 34461 ns/op 20960 B/op 749 allocs/op
BenchmarkHasClass-4 10000 232429 ns/op 14944 B/op 976 allocs/op
BenchmarkContains-4 200000000 7.62 ns/op 0 B/op 0 allocs/op
BenchmarkFind-4 100000 16114 ns/op 3839 B/op 21 allocs/op
BenchmarkFindWithinSelection-4 30000 42520 ns/op 3540 B/op 82 allocs/op
BenchmarkFindSelection-4 10000 209801 ns/op 5615 B/op 89 allocs/op
BenchmarkFindNodes-4 10000 209082 ns/op 5614 B/op 89 allocs/op
BenchmarkContents-4 300000 4836 ns/op 1420 B/op 36 allocs/op
BenchmarkContentsFiltered-4 200000 5495 ns/op 1570 B/op 41 allocs/op
BenchmarkChildren-4 3000000 527 ns/op 152 B/op 7 allocs/op
BenchmarkChildrenFiltered-4 500000 2499 ns/op 352 B/op 15 allocs/op
BenchmarkParent-4 50000 34072 ns/op 6942 B/op 387 allocs/op
BenchmarkParentFiltered-4 50000 36077 ns/op 7141 B/op 394 allocs/op
BenchmarkParents-4 20000 64118 ns/op 30719 B/op 837 allocs/op
BenchmarkParentsFiltered-4 20000 63432 ns/op 31303 B/op 845 allocs/op
BenchmarkParentsUntil-4 50000 29589 ns/op 11829 B/op 358 allocs/op
BenchmarkParentsUntilSelection-4 10000 101033 ns/op 54076 B/op 1523 allocs/op
BenchmarkParentsUntilNodes-4 10000 100584 ns/op 54076 B/op 1523 allocs/op
BenchmarkParentsFilteredUntil-4 200000 8061 ns/op 2787 B/op 88 allocs/op
BenchmarkParentsFilteredUntilSelection-4 100000 13848 ns/op 5995 B/op 192 allocs/op
BenchmarkParentsFilteredUntilNodes-4 100000 13766 ns/op 5995 B/op 192 allocs/op
BenchmarkSiblings-4 20000 75135 ns/op 28453 B/op 225 allocs/op
BenchmarkSiblingsFiltered-4 20000 80532 ns/op 29544 B/op 234 allocs/op
BenchmarkNext-4 100000 14200 ns/op 4660 B/op 117 allocs/op
BenchmarkNextFiltered-4 100000 15284 ns/op 4859 B/op 123 allocs/op
BenchmarkNextAll-4 20000 60889 ns/op 22774 B/op 157 allocs/op
BenchmarkNextAllFiltered-4 20000 65125 ns/op 23869 B/op 166 allocs/op
BenchmarkPrev-4 100000 14448 ns/op 4659 B/op 117 allocs/op
BenchmarkPrevFiltered-4 100000 15444 ns/op 4859 B/op 123 allocs/op
BenchmarkPrevAll-4 100000 22019 ns/op 7344 B/op 120 allocs/op
BenchmarkPrevAllFiltered-4 100000 23307 ns/op 7545 B/op 126 allocs/op
BenchmarkNextUntil-4 50000 30287 ns/op 8766 B/op 267 allocs/op
BenchmarkNextUntilSelection-4 30000 41476 ns/op 19862 B/op 546 allocs/op
BenchmarkNextUntilNodes-4 100000 16106 ns/op 8133 B/op 249 allocs/op
BenchmarkPrevUntil-4 20000 98951 ns/op 25728 B/op 467 allocs/op
BenchmarkPrevUntilSelection-4 30000 52390 ns/op 24875 B/op 694 allocs/op
BenchmarkPrevUntilNodes-4 100000 12986 ns/op 6334 B/op 204 allocs/op
BenchmarkNextFilteredUntil-4 100000 19365 ns/op 5908 B/op 177 allocs/op
BenchmarkNextFilteredUntilSelection-4 30000 45334 ns/op 20555 B/op 571 allocs/op
BenchmarkNextFilteredUntilNodes-4 30000 45292 ns/op 20556 B/op 571 allocs/op
BenchmarkPrevFilteredUntil-4 100000 19412 ns/op 6032 B/op 179 allocs/op
BenchmarkPrevFilteredUntilSelection-4 30000 46286 ns/op 21304 B/op 591 allocs/op
BenchmarkPrevFilteredUntilNodes-4 30000 46554 ns/op 21305 B/op 591 allocs/op
BenchmarkClosest-4 500000 3480 ns/op 160 B/op 8 allocs/op
BenchmarkClosestSelection-4 2000000 722 ns/op 96 B/op 6 allocs/op
BenchmarkClosestNodes-4 2000000 719 ns/op 96 B/op 6 allocs/op
PASS
ok github.com/PuerkitoBio/goquery 160.565s
+12 -4
View File
@@ -70,7 +70,9 @@ func BenchmarkIndex(b *testing.B) {
for i := 0; i < b.N; i++ {
j = sel.Index()
}
b.Logf("Index=%d", j)
if j != 3 {
b.Fatalf("want 3, got %d", j)
}
}
func BenchmarkIndexSelector(b *testing.B) {
@@ -82,7 +84,9 @@ func BenchmarkIndexSelector(b *testing.B) {
for i := 0; i < b.N; i++ {
j = sel.IndexSelector("dd")
}
b.Logf("IndexSelector=%d", j)
if j != 4 {
b.Fatalf("want 4, got %d", j)
}
}
func BenchmarkIndexOfNode(b *testing.B) {
@@ -96,7 +100,9 @@ func BenchmarkIndexOfNode(b *testing.B) {
for i := 0; i < b.N; i++ {
j = sel.IndexOfNode(n)
}
b.Logf("IndexOfNode=%d", j)
if j != 2 {
b.Fatalf("want 2, got %d", j)
}
}
func BenchmarkIndexOfSelection(b *testing.B) {
@@ -108,5 +114,7 @@ func BenchmarkIndexOfSelection(b *testing.B) {
for i := 0; i < b.N; i++ {
j = sel.IndexOfSelection(sel2)
}
b.Logf("IndexOfSelection=%d", j)
if j != 2 {
b.Fatalf("want 2, got %d", j)
}
}
-2
View File
@@ -37,6 +37,4 @@ func BenchmarkMetalReviewExample(b *testing.B) {
}
})
}
b.Log(buf.String())
b.Logf("MetalReviewExample=%d", n)
}
+36 -4
View File
@@ -17,7 +17,9 @@ func BenchmarkAdd(b *testing.B) {
sel.Add("h2[title]")
}
}
b.Logf("Add=%d", n)
if n != 43 {
b.Fatalf("want 43, got %d", n)
}
}
func BenchmarkAddSelection(b *testing.B) {
@@ -34,7 +36,9 @@ func BenchmarkAddSelection(b *testing.B) {
sel.AddSelection(sel2)
}
}
b.Logf("AddSelection=%d", n)
if n != 43 {
b.Fatalf("want 43, got %d", n)
}
}
func BenchmarkAddNodes(b *testing.B) {
@@ -52,7 +56,33 @@ func BenchmarkAddNodes(b *testing.B) {
sel.AddNodes(nodes...)
}
}
b.Logf("AddNodes=%d", n)
if n != 43 {
b.Fatalf("want 43, got %d", n)
}
}
func BenchmarkAddNodesBig(b *testing.B) {
var n int
doc := DocW()
sel := doc.Find("li")
// make nodes > 1000
nodes := sel.Nodes
nodes = append(nodes, nodes...)
nodes = append(nodes, nodes...)
sel = doc.Find("xyz")
b.ResetTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
n = sel.AddNodes(nodes...).Length()
} else {
sel.AddNodes(nodes...)
}
}
if n != 373 {
b.Fatalf("want 373, got %d", n)
}
}
func BenchmarkAndSelf(b *testing.B) {
@@ -68,5 +98,7 @@ func BenchmarkAndSelf(b *testing.B) {
sel.AndSelf()
}
}
b.Logf("AndSelf=%d", n)
if n != 44 {
b.Fatalf("want 44, got %d", n)
}
}
+36 -12
View File
@@ -17,7 +17,9 @@ func BenchmarkFilter(b *testing.B) {
sel.Filter(".toclevel-1")
}
}
b.Logf("Filter=%d", n)
if n != 13 {
b.Fatalf("want 13, got %d", n)
}
}
func BenchmarkNot(b *testing.B) {
@@ -33,7 +35,9 @@ func BenchmarkNot(b *testing.B) {
sel.Filter(".toclevel-2")
}
}
b.Logf("Not=%d", n)
if n != 371 {
b.Fatalf("want 371, got %d", n)
}
}
func BenchmarkFilterFunction(b *testing.B) {
@@ -52,7 +56,9 @@ func BenchmarkFilterFunction(b *testing.B) {
sel.FilterFunction(f)
}
}
b.Logf("FilterFunction=%d", n)
if n != 112 {
b.Fatalf("want 112, got %d", n)
}
}
func BenchmarkNotFunction(b *testing.B) {
@@ -71,7 +77,9 @@ func BenchmarkNotFunction(b *testing.B) {
sel.NotFunction(f)
}
}
b.Logf("NotFunction=%d", n)
if n != 261 {
b.Fatalf("want 261, got %d", n)
}
}
func BenchmarkFilterNodes(b *testing.B) {
@@ -89,7 +97,9 @@ func BenchmarkFilterNodes(b *testing.B) {
sel.FilterNodes(nodes...)
}
}
b.Logf("FilterNodes=%d", n)
if n != 2 {
b.Fatalf("want 2, got %d", n)
}
}
func BenchmarkNotNodes(b *testing.B) {
@@ -107,7 +117,9 @@ func BenchmarkNotNodes(b *testing.B) {
sel.NotNodes(nodes...)
}
}
b.Logf("NotNodes=%d", n)
if n != 360 {
b.Fatalf("want 360, got %d", n)
}
}
func BenchmarkFilterSelection(b *testing.B) {
@@ -124,7 +136,9 @@ func BenchmarkFilterSelection(b *testing.B) {
sel.FilterSelection(sel2)
}
}
b.Logf("FilterSelection=%d", n)
if n != 2 {
b.Fatalf("want 2, got %d", n)
}
}
func BenchmarkNotSelection(b *testing.B) {
@@ -141,7 +155,9 @@ func BenchmarkNotSelection(b *testing.B) {
sel.NotSelection(sel2)
}
}
b.Logf("NotSelection=%d", n)
if n != 360 {
b.Fatalf("want 360, got %d", n)
}
}
func BenchmarkHas(b *testing.B) {
@@ -157,7 +173,9 @@ func BenchmarkHas(b *testing.B) {
sel.Has(".editsection")
}
}
b.Logf("Has=%d", n)
if n != 13 {
b.Fatalf("want 13, got %d", n)
}
}
func BenchmarkHasNodes(b *testing.B) {
@@ -175,7 +193,9 @@ func BenchmarkHasNodes(b *testing.B) {
sel.HasNodes(nodes...)
}
}
b.Logf("HasNodes=%d", n)
if n != 15 {
b.Fatalf("want 15, got %d", n)
}
}
func BenchmarkHasSelection(b *testing.B) {
@@ -192,7 +212,9 @@ func BenchmarkHasSelection(b *testing.B) {
sel.HasSelection(sel2)
}
}
b.Logf("HasSelection=%d", n)
if n != 15 {
b.Fatalf("want 15, got %d", n)
}
}
func BenchmarkEnd(b *testing.B) {
@@ -208,5 +230,7 @@ func BenchmarkEnd(b *testing.B) {
sel.End()
}
}
b.Logf("End=%d", n)
if n != 373 {
b.Fatalf("wnat 373, got %d", n)
}
}
+9 -3
View File
@@ -19,7 +19,9 @@ func BenchmarkEach(b *testing.B) {
n = tmp
}
}
b.Logf("Each=%d", n)
if n != 59 {
b.Fatalf("want 59, got %d", n)
}
}
func BenchmarkMap(b *testing.B) {
@@ -38,7 +40,9 @@ func BenchmarkMap(b *testing.B) {
n = tmp
}
}
b.Logf("Map=%d", n)
if n != 59 {
b.Fatalf("want 59, got %d", n)
}
}
func BenchmarkEachWithBreak(b *testing.B) {
@@ -58,5 +62,7 @@ func BenchmarkEachWithBreak(b *testing.B) {
n = tmp
}
}
b.Logf("Each=%d", n)
if n != 10 {
b.Fatalf("want 10, got %d", n)
}
}
+6 -2
View File
@@ -13,7 +13,9 @@ func BenchmarkAttr(b *testing.B) {
for i := 0; i < b.N; i++ {
s, _ = sel.Attr("id")
}
b.Logf("Attr=%s", s)
if s != "firstHeading" {
b.Fatalf("want firstHeading, got %q", s)
}
}
func BenchmarkText(b *testing.B) {
@@ -34,7 +36,9 @@ func BenchmarkLength(b *testing.B) {
for i := 0; i < b.N; i++ {
n = sel.Length()
}
b.Logf("Length=%d", n)
if n != 14 {
b.Fatalf("want 14, got %d", n)
}
}
func BenchmarkHtml(b *testing.B) {
+21 -7
View File
@@ -13,7 +13,9 @@ func BenchmarkIs(b *testing.B) {
for i := 0; i < b.N; i++ {
y = sel.Is(".toclevel-2")
}
b.Logf("Is=%v", y)
if !y {
b.Fatal("want true")
}
}
func BenchmarkIsPositional(b *testing.B) {
@@ -25,7 +27,9 @@ func BenchmarkIsPositional(b *testing.B) {
for i := 0; i < b.N; i++ {
y = sel.Is("li:nth-child(2)")
}
b.Logf("IsPositional=%v", y)
if !y {
b.Fatal("want true")
}
}
func BenchmarkIsFunction(b *testing.B) {
@@ -40,7 +44,9 @@ func BenchmarkIsFunction(b *testing.B) {
for i := 0; i < b.N; i++ {
y = sel.IsFunction(f)
}
b.Logf("IsFunction=%v", y)
if !y {
b.Fatal("want true")
}
}
func BenchmarkIsSelection(b *testing.B) {
@@ -53,7 +59,9 @@ func BenchmarkIsSelection(b *testing.B) {
for i := 0; i < b.N; i++ {
y = sel.IsSelection(sel2)
}
b.Logf("IsSelection=%v", y)
if !y {
b.Fatal("want true")
}
}
func BenchmarkIsNodes(b *testing.B) {
@@ -67,7 +75,9 @@ func BenchmarkIsNodes(b *testing.B) {
for i := 0; i < b.N; i++ {
y = sel.IsNodes(nodes...)
}
b.Logf("IsNodes=%v", y)
if !y {
b.Fatal("want true")
}
}
func BenchmarkHasClass(b *testing.B) {
@@ -79,7 +89,9 @@ func BenchmarkHasClass(b *testing.B) {
for i := 0; i < b.N; i++ {
y = sel.HasClass("official")
}
b.Logf("HasClass=%v", y)
if !y {
b.Fatal("want true")
}
}
func BenchmarkContains(b *testing.B) {
@@ -93,5 +105,7 @@ func BenchmarkContains(b *testing.B) {
for i := 0; i < b.N; i++ {
y = sel.Contains(node)
}
b.Logf("Contains=%v", y)
if !y {
b.Fatal("want true")
}
}
+129 -43
View File
@@ -15,7 +15,9 @@ func BenchmarkFind(b *testing.B) {
DocB().Find("dd")
}
}
b.Logf("Find=%d", n)
if n != 41 {
b.Fatalf("want 41, got %d", n)
}
}
func BenchmarkFindWithinSelection(b *testing.B) {
@@ -31,7 +33,9 @@ func BenchmarkFindWithinSelection(b *testing.B) {
sel.Find("a[class]")
}
}
b.Logf("FindWithinSelection=%d", n)
if n != 39 {
b.Fatalf("want 39, got %d", n)
}
}
func BenchmarkFindSelection(b *testing.B) {
@@ -48,7 +52,9 @@ func BenchmarkFindSelection(b *testing.B) {
sel.FindSelection(sel2)
}
}
b.Logf("FindSelection=%d", n)
if n != 73 {
b.Fatalf("want 73, got %d", n)
}
}
func BenchmarkFindNodes(b *testing.B) {
@@ -66,7 +72,9 @@ func BenchmarkFindNodes(b *testing.B) {
sel.FindNodes(nodes...)
}
}
b.Logf("FindNodes=%d", n)
if n != 73 {
b.Fatalf("want 73, got %d", n)
}
}
func BenchmarkContents(b *testing.B) {
@@ -82,7 +90,9 @@ func BenchmarkContents(b *testing.B) {
sel.Contents()
}
}
b.Logf("Contents=%d", n)
if n != 16 {
b.Fatalf("want 16, got %d", n)
}
}
func BenchmarkContentsFiltered(b *testing.B) {
@@ -98,7 +108,9 @@ func BenchmarkContentsFiltered(b *testing.B) {
sel.ContentsFiltered("a[href=\"#Examples\"]")
}
}
b.Logf("ContentsFiltered=%d", n)
if n != 1 {
b.Fatalf("want 1, got %d", n)
}
}
func BenchmarkChildren(b *testing.B) {
@@ -114,7 +126,9 @@ func BenchmarkChildren(b *testing.B) {
sel.Children()
}
}
b.Logf("Children=%d", n)
if n != 2 {
b.Fatalf("want 2, got %d", n)
}
}
func BenchmarkChildrenFiltered(b *testing.B) {
@@ -130,7 +144,9 @@ func BenchmarkChildrenFiltered(b *testing.B) {
sel.ChildrenFiltered(".editsection")
}
}
b.Logf("ChildrenFiltered=%d", n)
if n != 2 {
b.Fatalf("want 2, got %d", n)
}
}
func BenchmarkParent(b *testing.B) {
@@ -146,7 +162,9 @@ func BenchmarkParent(b *testing.B) {
sel.Parent()
}
}
b.Logf("Parent=%d", n)
if n != 55 {
b.Fatalf("want 55, got %d", n)
}
}
func BenchmarkParentFiltered(b *testing.B) {
@@ -162,7 +180,9 @@ func BenchmarkParentFiltered(b *testing.B) {
sel.ParentFiltered("ul[id]")
}
}
b.Logf("ParentFiltered=%d", n)
if n != 4 {
b.Fatalf("want 4, got %d", n)
}
}
func BenchmarkParents(b *testing.B) {
@@ -178,7 +198,9 @@ func BenchmarkParents(b *testing.B) {
sel.Parents()
}
}
b.Logf("Parents=%d", n)
if n != 73 {
b.Fatalf("want 73, got %d", n)
}
}
func BenchmarkParentsFiltered(b *testing.B) {
@@ -194,7 +216,9 @@ func BenchmarkParentsFiltered(b *testing.B) {
sel.ParentsFiltered("tr")
}
}
b.Logf("ParentsFiltered=%d", n)
if n != 18 {
b.Fatalf("want 18, got %d", n)
}
}
func BenchmarkParentsUntil(b *testing.B) {
@@ -210,7 +234,9 @@ func BenchmarkParentsUntil(b *testing.B) {
sel.ParentsUntil("table")
}
}
b.Logf("ParentsUntil=%d", n)
if n != 52 {
b.Fatalf("want 52, got %d", n)
}
}
func BenchmarkParentsUntilSelection(b *testing.B) {
@@ -227,7 +253,9 @@ func BenchmarkParentsUntilSelection(b *testing.B) {
sel.ParentsUntilSelection(sel2)
}
}
b.Logf("ParentsUntilSelection=%d", n)
if n != 70 {
b.Fatalf("want 70, got %d", n)
}
}
func BenchmarkParentsUntilNodes(b *testing.B) {
@@ -245,7 +273,9 @@ func BenchmarkParentsUntilNodes(b *testing.B) {
sel.ParentsUntilNodes(nodes...)
}
}
b.Logf("ParentsUntilNodes=%d", n)
if n != 70 {
b.Fatalf("want 70, got %d", n)
}
}
func BenchmarkParentsFilteredUntil(b *testing.B) {
@@ -261,7 +291,9 @@ func BenchmarkParentsFilteredUntil(b *testing.B) {
sel.ParentsFilteredUntil(":nth-child(1)", "ul")
}
}
b.Logf("ParentsFilteredUntil=%d", n)
if n != 2 {
b.Fatalf("want 2, got %d", n)
}
}
func BenchmarkParentsFilteredUntilSelection(b *testing.B) {
@@ -278,7 +310,9 @@ func BenchmarkParentsFilteredUntilSelection(b *testing.B) {
sel.ParentsFilteredUntilSelection(":nth-child(1)", sel2)
}
}
b.Logf("ParentsFilteredUntilSelection=%d", n)
if n != 2 {
b.Fatalf("want 2, got %d", n)
}
}
func BenchmarkParentsFilteredUntilNodes(b *testing.B) {
@@ -296,7 +330,9 @@ func BenchmarkParentsFilteredUntilNodes(b *testing.B) {
sel.ParentsFilteredUntilNodes(":nth-child(1)", nodes...)
}
}
b.Logf("ParentsFilteredUntilNodes=%d", n)
if n != 2 {
b.Fatalf("want 2, got %d", n)
}
}
func BenchmarkSiblings(b *testing.B) {
@@ -312,7 +348,9 @@ func BenchmarkSiblings(b *testing.B) {
sel.Siblings()
}
}
b.Logf("Siblings=%d", n)
if n != 293 {
b.Fatalf("want 293, got %d", n)
}
}
func BenchmarkSiblingsFiltered(b *testing.B) {
@@ -328,7 +366,9 @@ func BenchmarkSiblingsFiltered(b *testing.B) {
sel.SiblingsFiltered("[class]")
}
}
b.Logf("SiblingsFiltered=%d", n)
if n != 46 {
b.Fatalf("want 46, got %d", n)
}
}
func BenchmarkNext(b *testing.B) {
@@ -344,7 +384,9 @@ func BenchmarkNext(b *testing.B) {
sel.Next()
}
}
b.Logf("Next=%d", n)
if n != 49 {
b.Fatalf("want 49, got %d", n)
}
}
func BenchmarkNextFiltered(b *testing.B) {
@@ -360,7 +402,9 @@ func BenchmarkNextFiltered(b *testing.B) {
sel.NextFiltered("[class]")
}
}
b.Logf("NextFiltered=%d", n)
if n != 6 {
b.Fatalf("want 6, got %d", n)
}
}
func BenchmarkNextAll(b *testing.B) {
@@ -376,7 +420,9 @@ func BenchmarkNextAll(b *testing.B) {
sel.NextAll()
}
}
b.Logf("NextAll=%d", n)
if n != 234 {
b.Fatalf("want 234, got %d", n)
}
}
func BenchmarkNextAllFiltered(b *testing.B) {
@@ -392,7 +438,9 @@ func BenchmarkNextAllFiltered(b *testing.B) {
sel.NextAllFiltered("[class]")
}
}
b.Logf("NextAllFiltered=%d", n)
if n != 33 {
b.Fatalf("want 33, got %d", n)
}
}
func BenchmarkPrev(b *testing.B) {
@@ -408,7 +456,9 @@ func BenchmarkPrev(b *testing.B) {
sel.Prev()
}
}
b.Logf("Prev=%d", n)
if n != 49 {
b.Fatalf("want 49, got %d", n)
}
}
func BenchmarkPrevFiltered(b *testing.B) {
@@ -426,7 +476,9 @@ func BenchmarkPrevFiltered(b *testing.B) {
}
// There is one more Prev li with a class, compared to Next li with a class
// (confirmed by looking at the HTML, this is ok)
b.Logf("PrevFiltered=%d", n)
if n != 7 {
b.Fatalf("want 7, got %d", n)
}
}
func BenchmarkPrevAll(b *testing.B) {
@@ -442,7 +494,9 @@ func BenchmarkPrevAll(b *testing.B) {
sel.PrevAll()
}
}
b.Logf("PrevAll=%d", n)
if n != 78 {
b.Fatalf("want 78, got %d", n)
}
}
func BenchmarkPrevAllFiltered(b *testing.B) {
@@ -458,7 +512,9 @@ func BenchmarkPrevAllFiltered(b *testing.B) {
sel.PrevAllFiltered("[class]")
}
}
b.Logf("PrevAllFiltered=%d", n)
if n != 6 {
b.Fatalf("want 6, got %d", n)
}
}
func BenchmarkNextUntil(b *testing.B) {
@@ -474,7 +530,9 @@ func BenchmarkNextUntil(b *testing.B) {
sel.NextUntil(":nth-child(4)")
}
}
b.Logf("NextUntil=%d", n)
if n != 84 {
b.Fatalf("want 84, got %d", n)
}
}
func BenchmarkNextUntilSelection(b *testing.B) {
@@ -491,7 +549,9 @@ func BenchmarkNextUntilSelection(b *testing.B) {
sel.NextUntilSelection(sel2)
}
}
b.Logf("NextUntilSelection=%d", n)
if n != 42 {
b.Fatalf("want 42, got %d", n)
}
}
func BenchmarkNextUntilNodes(b *testing.B) {
@@ -509,7 +569,9 @@ func BenchmarkNextUntilNodes(b *testing.B) {
sel.NextUntilNodes(nodes...)
}
}
b.Logf("NextUntilNodes=%d", n)
if n != 12 {
b.Fatalf("want 12, got %d", n)
}
}
func BenchmarkPrevUntil(b *testing.B) {
@@ -525,7 +587,9 @@ func BenchmarkPrevUntil(b *testing.B) {
sel.PrevUntil(":nth-child(4)")
}
}
b.Logf("PrevUntil=%d", n)
if n != 238 {
b.Fatalf("want 238, got %d", n)
}
}
func BenchmarkPrevUntilSelection(b *testing.B) {
@@ -542,7 +606,9 @@ func BenchmarkPrevUntilSelection(b *testing.B) {
sel.PrevUntilSelection(sel2)
}
}
b.Logf("PrevUntilSelection=%d", n)
if n != 49 {
b.Fatalf("want 49, got %d", n)
}
}
func BenchmarkPrevUntilNodes(b *testing.B) {
@@ -560,7 +626,9 @@ func BenchmarkPrevUntilNodes(b *testing.B) {
sel.PrevUntilNodes(nodes...)
}
}
b.Logf("PrevUntilNodes=%d", n)
if n != 11 {
b.Fatalf("want 11, got %d", n)
}
}
func BenchmarkNextFilteredUntil(b *testing.B) {
@@ -576,7 +644,9 @@ func BenchmarkNextFilteredUntil(b *testing.B) {
sel.NextFilteredUntil("p", "div")
}
}
b.Logf("NextFilteredUntil=%d", n)
if n != 22 {
b.Fatalf("want 22, got %d", n)
}
}
func BenchmarkNextFilteredUntilSelection(b *testing.B) {
@@ -593,7 +663,9 @@ func BenchmarkNextFilteredUntilSelection(b *testing.B) {
sel.NextFilteredUntilSelection("p", sel2)
}
}
b.Logf("NextFilteredUntilSelection=%d", n)
if n != 22 {
b.Fatalf("want 22, got %d", n)
}
}
func BenchmarkNextFilteredUntilNodes(b *testing.B) {
@@ -611,7 +683,9 @@ func BenchmarkNextFilteredUntilNodes(b *testing.B) {
sel.NextFilteredUntilNodes("p", nodes...)
}
}
b.Logf("NextFilteredUntilNodes=%d", n)
if n != 22 {
b.Fatalf("want 22, got %d", n)
}
}
func BenchmarkPrevFilteredUntil(b *testing.B) {
@@ -627,7 +701,9 @@ func BenchmarkPrevFilteredUntil(b *testing.B) {
sel.PrevFilteredUntil("p", "div")
}
}
b.Logf("PrevFilteredUntil=%d", n)
if n != 20 {
b.Fatalf("want 20, got %d", n)
}
}
func BenchmarkPrevFilteredUntilSelection(b *testing.B) {
@@ -644,7 +720,9 @@ func BenchmarkPrevFilteredUntilSelection(b *testing.B) {
sel.PrevFilteredUntilSelection("p", sel2)
}
}
b.Logf("PrevFilteredUntilSelection=%d", n)
if n != 20 {
b.Fatalf("want 20, got %d", n)
}
}
func BenchmarkPrevFilteredUntilNodes(b *testing.B) {
@@ -662,7 +740,9 @@ func BenchmarkPrevFilteredUntilNodes(b *testing.B) {
sel.PrevFilteredUntilNodes("p", nodes...)
}
}
b.Logf("PrevFilteredUntilNodes=%d", n)
if n != 20 {
b.Fatalf("want 20, got %d", n)
}
}
func BenchmarkClosest(b *testing.B) {
@@ -678,7 +758,9 @@ func BenchmarkClosest(b *testing.B) {
sel.Closest(".pvk-content")
}
}
b.Logf("Closest=%d", n)
if n != 2 {
b.Fatalf("want 2, got %d", n)
}
}
func BenchmarkClosestSelection(b *testing.B) {
@@ -695,7 +777,9 @@ func BenchmarkClosestSelection(b *testing.B) {
sel.ClosestSelection(sel2)
}
}
b.Logf("ClosestSelection=%d", n)
if n != 2 {
b.Fatalf("want 2, got %d", n)
}
}
func BenchmarkClosestNodes(b *testing.B) {
@@ -712,5 +796,7 @@ func BenchmarkClosestNodes(b *testing.B) {
sel.ClosestNodes(nodes...)
}
}
b.Logf("ClosestNodes=%d", n)
if n != 2 {
b.Fatalf("want 2, got %d", n)
}
}
+1 -1
View File
@@ -35,7 +35,7 @@ func (s *Selection) Union(sel *Selection) *Selection {
// AddNodes adds the specified nodes to those in the
// current selection and returns a new Selection object.
func (s *Selection) AddNodes(nodes ...*html.Node) *Selection {
return pushStack(s, appendWithoutDuplicates(s.Nodes, nodes))
return pushStack(s, appendWithoutDuplicates(s.Nodes, nodes, nil))
}
// AndSelf adds the previous set of elements on the stack to the current set.
+18
View File
@@ -66,6 +66,24 @@ func TestAddNodesRollback(t *testing.T) {
assertEqual(t, sel, sel2)
}
func TestAddNodesBig(t *testing.T) {
doc := DocW()
sel := doc.Find("li")
assertLength(t, sel.Nodes, 373)
sel2 := doc.Find("xyz")
assertLength(t, sel2.Nodes, 0)
nodes := sel.Nodes
sel2 = sel2.AddNodes(nodes...)
assertLength(t, sel2.Nodes, 373)
nodes2 := append(nodes, nodes...)
sel2 = sel2.End().AddNodes(nodes2...)
assertLength(t, sel2.Nodes, 373)
nodes3 := append(nodes2, nodes...)
sel2 = sel2.End().AddNodes(nodes3...)
assertLength(t, sel2.Nodes, 373)
}
func TestAndSelf(t *testing.T) {
sel := Doc().Find(".span12").Last().AndSelf()
assertLength(t, sel.Nodes, 2)
+11 -1
View File
@@ -139,8 +139,18 @@ func winnow(sel *Selection, m Matcher, keep bool) []*html.Node {
// Filter based on an array of nodes, and the indicator to keep (Filter) or
// 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
})
}
set := make(map[*html.Node]bool)
for _, n := range nodes {
set[n] = true
}
return grep(sel, func(i int, s *Selection) bool {
return isInSlice(nodes, s.Get(0)) == keep
return set[s.Get(0)] == keep
})
}
+42 -27
View File
@@ -1,37 +1,52 @@
#!/bin/sh
# Copyright 2012 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# git gofmt pre-commit hook
#
# To use, store as .git/hooks/pre-commit inside your repository and make sure
# it has execute permissions.
#
# This script does not handle file names that contain spaces.
echo ">>> golint"
for dir in $(go list ./... | grep -v /vendor/)
do
golint "${dir}"
done
echo "<<< golint"
echo
# golint is purely informational, it doesn't fail with exit code != 0 if it finds something,
# because it may find a lot of false positives. Just print out its result for information.
echo "lint result (informational only):"
golint .
echo ">>> go vet"
go vet $(go list ./... | grep -v /vendor/)
echo "<<< go vet"
echo
# go vet returns 1 if an error was found. Exit the hook with this exit code.
go vet ./...
vetres=$?
echo ">>> gosimple"
gosimple $(go list ./... | grep -v /vendor/)
echo "<<< gosimple"
echo
echo ">>> staticcheck"
staticcheck $(go list ./... | grep -v /vendor/)
echo "<<< staticcheck"
echo
echo ">>> unused"
unused $(go list ./... | grep -v /vendor/)
echo "<<< unused"
echo
echo ">>> gas"
gas $(find . -name "*.go" | grep -v /vendor/ | grep -v '_test.go$')
echo "<<< gas"
echo
# Check for gofmt problems and report if any.
gofiles=$(git diff --cached --name-only --diff-filter=ACM | grep '.go$')
gofiles=$(git diff --cached --name-only --diff-filter=ACM | grep '.go$' | grep -v /vendor/)
[ -z "$gofiles" ] && echo "EXIT $vetres" && exit $vetres
unformatted=$(gofmt -l $gofiles)
[ -z "$unformatted" ] && echo "EXIT $vetres" && exit $vetres
if [ -n "$gofiles" ]; then
unformatted=$(gofmt -l $gofiles)
# Some files are not gofmt'd. Print message and fail.
if [ -n "$unformatted" ]; then
# Some files are not gofmt'd.
echo >&2 "Go files must be formatted with gofmt. Please run:"
for fn in $unformatted; do
echo >&2 " gofmt -w $PWD/$fn"
done
fi
fi
echo
echo >&2 "Go files must be formatted with gofmt. Please run:"
for fn in $unformatted; do
echo >&2 " gofmt -w $PWD/$fn"
done
echo "EXIT 1"
exit 1
+3 -3
View File
@@ -112,7 +112,7 @@ func (s *Selection) AddClass(class ...string) *Selection {
for _, n := range s.Nodes {
curClasses, attr := getClassesAndAttr(n, true)
for _, newClass := range tcls {
if strings.Index(curClasses, " "+newClass+" ") == -1 {
if !strings.Contains(curClasses, " "+newClass+" ") {
curClasses += newClass + " "
}
}
@@ -129,7 +129,7 @@ func (s *Selection) HasClass(class string) bool {
class = " " + class + " "
for _, n := range s.Nodes {
classes, _ := getClassesAndAttr(n, false)
if strings.Index(classes, class) > -1 {
if strings.Contains(classes, class) {
return true
}
}
@@ -179,7 +179,7 @@ func (s *Selection) ToggleClass(class ...string) *Selection {
for _, n := range s.Nodes {
classes, attr := getClassesAndAttr(n, true)
for _, tcl := range tcls {
if strings.Index(classes, " "+tcl+" ") != -1 {
if strings.Contains(classes, " "+tcl+" ") {
classes = strings.Replace(classes, " "+tcl+" ", " ", -1)
} else {
classes += tcl + " "
+8 -3
View File
@@ -143,11 +143,15 @@ 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)
for _, n := range nodes {
set[n] = true
}
return pushStack(s, mapNodes(s.Nodes, func(i int, n *html.Node) []*html.Node {
// For each node in the selection, test the node itself, then each parent
// until a match is found.
for ; n != nil; n = n.Parent {
if isInSlice(nodes, n) {
if set[n] {
return []*html.Node{n}
}
}
@@ -684,10 +688,11 @@ 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)
for i, n := range nodes {
if vals := f(i, n); len(vals) > 0 {
result = appendWithoutDuplicates(result, vals)
result = appendWithoutDuplicates(result, vals, set)
}
}
return
return result
}
+10
View File
@@ -26,6 +26,16 @@ func TestFindInvalid(t *testing.T) {
assertLength(t, sel.Nodes, 0)
}
func TestFindBig(t *testing.T) {
doc := DocW()
sel := doc.Find("li")
assertLength(t, sel.Nodes, 373)
sel2 := doc.Find("span")
assertLength(t, sel2.Nodes, 448)
sel3 := sel.FindSelection(sel2)
assertLength(t, sel3.Nodes, 248)
}
func TestChainedFind(t *testing.T) {
sel := Doc().Find("div.hero-unit").Find(".row-fluid")
assertLength(t, sel.Nodes, 4)
+6 -22
View File
@@ -23,45 +23,42 @@ func Doc() *Document {
}
return doc
}
func DocClone() *Document {
return CloneDocument(Doc())
}
func Doc2() *Document {
if doc2 == nil {
doc2 = loadDoc("page2.html")
}
return doc2
}
func Doc2Clone() *Document {
return CloneDocument(Doc2())
}
func Doc3() *Document {
if doc3 == nil {
doc3 = loadDoc("page3.html")
}
return doc3
}
func Doc3Clone() *Document {
return CloneDocument(Doc3())
}
func DocB() *Document {
if docB == nil {
docB = loadDoc("gotesting.html")
}
return docB
}
func DocBClone() *Document {
return CloneDocument(DocB())
}
func DocW() *Document {
if docW == nil {
docW = loadDoc("gowiki.html")
}
return docW
}
func DocWClone() *Document {
return CloneDocument(DocW())
}
func assertLength(t *testing.T, nodes []*html.Node, length int) {
if len(nodes) != length {
@@ -108,19 +105,6 @@ func printSel(t *testing.T, sel *Selection) {
}
}
func shortPrintSel(t *testing.T, sel *Selection) {
sel.Each(func(i int, s *Selection) {
h, _ := OuterHtml(s)
if ix := strings.Index(h, "\n"); ix >= 0 {
h = h[:ix]
}
if len(h) > 100 {
h = h[:100]
}
fmt.Println(i, ">>> ", h)
})
}
func loadDoc(page string) *Document {
var f *os.File
var e error
+29 -10
View File
@@ -6,6 +6,11 @@ import (
"golang.org/x/net/html"
)
// used to determine if a set (map[*html.Node]bool) should be used
// instead of iterating over a slice. The set uses more memory and
// is slower than slice iteration for small N.
const minNodesForSet = 1000
var nodeNames = []string{
html.ErrorNode: "#error",
html.TextNode: "#text",
@@ -62,13 +67,6 @@ func OuterHtml(s *Selection) (string, error) {
return buf.String(), nil
}
func getChildren(n *html.Node) (result []*html.Node) {
for c := n.FirstChild; c != nil; c = c.NextSibling {
result = append(result, c)
}
return result
}
// Loop through all container nodes to search for the target node.
func sliceContains(container []*html.Node, contained *html.Node) bool {
for _, n := range container {
@@ -112,11 +110,32 @@ func indexInSlice(slice []*html.Node, node *html.Node) int {
// Appends the new nodes to the target slice, making sure no duplicate is added.
// There is no check to the original state of the target slice, so it may still
// contain duplicates. The target slice is returned because append() may create
// a new underlying array.
func appendWithoutDuplicates(target []*html.Node, nodes []*html.Node) []*html.Node {
// a new underlying array. If targetSet is nil, a local set is created with the
// target if len(target) + len(nodes) is greater than minNodesForSet.
func appendWithoutDuplicates(target []*html.Node, nodes []*html.Node, targetSet map[*html.Node]bool) []*html.Node {
// if there are not that many nodes, don't use the map, faster to just use nested loops
// (unless a non-nil targetSet is passed, in which case the caller knows better).
if targetSet == nil && len(target)+len(nodes) < minNodesForSet {
for _, n := range nodes {
if !isInSlice(target, n) {
target = append(target, n)
}
}
return target
}
// if a targetSet is passed, then assume it is reliable, otherwise create one
// and initialize it with the current target contents.
if targetSet == nil {
targetSet = make(map[*html.Node]bool, len(target))
for _, n := range target {
targetSet[n] = true
}
}
for _, n := range nodes {
if !isInSlice(target, n) {
if !targetSet[n] {
target = append(target, n)
targetSet[n] = true
}
}