From 57c58303d5d9dc9f9fc5729b3a7bf17939a7d74b Mon Sep 17 00:00:00 2001 From: Cleydyr Albuquerque Date: Sat, 9 Oct 2021 13:11:29 +0200 Subject: [PATCH 1/2] improve performance using binary search --- xpath.js | 56 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/xpath.js b/xpath.js index d58a4b8..b7f0522 100644 --- a/xpath.js +++ b/xpath.js @@ -2980,6 +2980,22 @@ var xpath = (typeof exports === 'undefined') ? {} : exports; } }; + function compare(n1, n2) { + if (n1.lineNumber < n2.lineNumber) { + return -1; + } + + if (n1.lineNumber > n2.lineNumber) { + return 1; + } + + if (n1.columnNumber < n2.columnNumber) { + return -1; + } + + return 1; + } + function nodeOrder(n1, n2) { if (n1 === n2) { return 0; @@ -3056,14 +3072,38 @@ var xpath = (typeof exports === 'undefined') ? {} : exports; if (n1Par) { var cn = n1isAttr ? n1Par.attributes : n1Par.childNodes, len = cn.length; - for (var i = 0; i < len; i += 1) { - var n = cn[i]; - if (n === n1) { - return -1; - } - if (n === n2) { - return 1; - } + + var start = 0; + var end = len - 1; + + while (start <= end) { + var mid = Math.floor(start + (end - start)/2); + + var midNode = cn[mid]; + + var fn1 = compare(n1, midNode); + var fn2 = compare(n2, midNode); + + if (fn1 == 0) { + return -fn2; + } + + if (fn2 == 0) { + return fn1; + } + + if (fn1 < 0 && fn2 < 0) { + end = mid - 1; + } + else if (fn1 > 0 && fn2 > 0) { + start = mid + 1; + } + else if (fn1 < 0) { + return -1; + } + else { + return 1; + } } } From 51b676b62cfe4855d3084d2076838358449b092a Mon Sep 17 00:00:00 2001 From: Cleydyr Albuquerque Date: Sat, 9 Oct 2021 13:18:58 +0200 Subject: [PATCH 2/2] apply binary search to add method as well --- xpath.js | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/xpath.js b/xpath.js index b7f0522..256649b 100644 --- a/xpath.js +++ b/xpath.js @@ -3251,11 +3251,35 @@ var xpath = (typeof exports === 'undefined') ? {} : exports; return p.node; }; + XNodeSet.prototype.contains = function(n) { + if (this.nodes.length == 0) { + return false; + } + + var start = 0; + var end = this.nodes.length - 1; + + while (start <= end) { + var mid = Math.floor(start + (end - start)/2); + + var midNode = this.nodes[mid]; + + if (n === midNode) { + return true; + } + + if (compare(n, midNode) < 0) { + end = mid - 1; + } + else { + start = mid + 1; + } + } + }; + XNodeSet.prototype.add = function (n) { - for (var i = 0; i < this.nodes.length; i += 1) { - if (n === this.nodes[i]) { - return; - } + if (this.contains(n)) { + return; } this.tree = null;