mirror of https://github.com/gorhill/uBlock.git
225 lines
6.3 KiB
HTML
225 lines
6.3 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
</head>
|
|
<body style="font: 14px sans-serif">
|
|
<h1>HNTrieContainer test</h1>
|
|
<div><button id="test" type="button">Test!</button></div>
|
|
<div id="stdout"></div>
|
|
<script src="https://rawcdn.githack.com/gorhill/uBlock/1b6fea16da81d1df3e2efd5a31894f71ea04dbb1/src/js/hntrie.js"></script>
|
|
<!-- <script src="../../src/js/hntrie.js"></script> -->
|
|
<script src="hostname-pool.js"></script>
|
|
<script>
|
|
const createRandomLabel = function() {
|
|
return Math.random().toString(36).slice(2);
|
|
};
|
|
|
|
const stdout = function(s) {
|
|
const line = document.createElement('div');
|
|
const parent = document.getElementById('stdout');
|
|
let tooManyErrors = false;
|
|
if ( parent.childElementCount > 100 ) {
|
|
tooManyErrors = true;
|
|
line.textContent = 'Too many errors, aborting';
|
|
} else {
|
|
line.textContent = s;
|
|
}
|
|
parent.appendChild(line)
|
|
if ( tooManyErrors ) {
|
|
throw 'Aborting';
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
// Dictionary of hostnames
|
|
//
|
|
const FilterHostnameDict = function(hostnames) {
|
|
this.h = ''; // short-lived register
|
|
this.dict = new Set();
|
|
if ( hostnames !== undefined ) {
|
|
this.fromIterable(hostnames);
|
|
}
|
|
};
|
|
|
|
FilterHostnameDict.prototype = {
|
|
add: function(hn) {
|
|
if ( this.dict.has(hn) ) { return false; }
|
|
this.dict.add(hn);
|
|
return true;
|
|
},
|
|
fromIterable: function(hostnames) {
|
|
for ( let hn of hostnames ) {
|
|
this.add(hn);
|
|
}
|
|
return this;
|
|
},
|
|
matches: function(needle) {
|
|
while ( this.dict.has(needle) === false ) {
|
|
const pos = needle.indexOf('.');
|
|
if ( pos === -1 ) {
|
|
this.h = '';
|
|
return false;
|
|
}
|
|
needle = needle.slice(pos + 1);
|
|
}
|
|
this.h = needle;
|
|
return true;
|
|
},
|
|
};
|
|
|
|
/******************************************************************************/
|
|
|
|
const testFlavor = function(hostnames, name, matchesFn, hitFn) {
|
|
stdout('\xA0');
|
|
stdout('Testing ' + name + '...');
|
|
|
|
const t0 = performance.now();
|
|
|
|
for ( let i = 0; i < hostnames.length; i++ ) {
|
|
// Exact hits
|
|
let needle = hostnames[i];
|
|
if ( hitFn(matchesFn(needle)) === false ) {
|
|
stdout('Exact hits failed: ' + needle);
|
|
}
|
|
|
|
// Subdomain hits
|
|
needle = createRandomLabel() + '.' + hostnames[i];
|
|
if ( hitFn(matchesFn(needle)) === false ) {
|
|
stdout('Subdomain hits failed: ' + needle);
|
|
}
|
|
|
|
// Misses batch 1
|
|
needle = createRandomLabel() + '.com';
|
|
if ( hitFn(matchesFn(needle)) !== false ) {
|
|
stdout('Misses batch 1: ' + needle);
|
|
}
|
|
|
|
// Misses batch 2
|
|
needle = hostnames[i] + '.' + createRandomLabel();
|
|
if ( hitFn(matchesFn(needle)) !== false ) {
|
|
stdout('Misses batch 2: ' + needle);
|
|
}
|
|
|
|
// Misses batch 3
|
|
needle = hostnames[i];
|
|
let pos = needle.lastIndexOf('.');
|
|
if ( pos !== -1 ) {
|
|
needle = needle.slice(0, pos) + needle.slice(pos + 1);
|
|
if ( hitFn(matchesFn(needle)) !== false ) {
|
|
stdout('Misses batch 3: ' + needle);
|
|
}
|
|
}
|
|
}
|
|
|
|
const t1 = performance.now();
|
|
|
|
stdout(
|
|
name + ': ' +
|
|
(hostnames.length * 5).toLocaleString() +
|
|
' tests completed in ' +
|
|
(t1 - t0).toFixed(2) + ' ms'
|
|
);
|
|
};
|
|
|
|
const hnBigTrieJS = new HNTrieContainer();
|
|
const hnBigTrieWASM = new HNTrieContainer();
|
|
const hnBigTrieUnserialized = new HNTrieContainer();
|
|
|
|
Promise.all([
|
|
hnBigTrieJS.readyToUse(),
|
|
hnBigTrieWASM.readyToUse()
|
|
]).then(( ) => {
|
|
let t0 = performance.now();
|
|
const theSet = new FilterHostnameDict(hostnamePool);
|
|
let t1 = performance.now();
|
|
stdout('\xA0');
|
|
stdout(
|
|
'Set creation completed in ' +
|
|
(t1 - t0).toFixed(2) + ' ms'
|
|
);
|
|
|
|
t0 = performance.now();
|
|
const theTrieJS = hnBigTrieJS.fromIterable(hostnamePool, 'addJS');
|
|
hnBigTrieJS.optimize();
|
|
t1 = performance.now();
|
|
stdout('\xA0');
|
|
stdout(
|
|
'HNTrieContainer creation (JS) completed in ' +
|
|
(t1 - t0).toFixed(2) + ' ms'
|
|
);
|
|
|
|
let theTrieWASM;
|
|
if ( hnBigTrieWASM.addWASM instanceof Function ) {
|
|
t0 = performance.now();
|
|
theTrieWASM = hnBigTrieWASM.fromIterable(hostnamePool, 'addWASM');
|
|
hnBigTrieWASM.optimize();
|
|
t1 = performance.now();
|
|
stdout('\xA0');
|
|
stdout(
|
|
'HNTrieContainer creation (WASM) completed in ' +
|
|
(t1 - t0).toFixed(2) + ' ms'
|
|
);
|
|
|
|
const bufJS = theTrieJS.container.buf;
|
|
const bufWASM = theTrieWASM.container.buf;
|
|
for ( let i = 0; i < bufJS.length; i++ ) {
|
|
if ( bufJS[i] !== bufWASM[i] ) {
|
|
stdout('theTrieWASM failure at index ' + i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
let selfie = hnBigTrieJS.serialize();
|
|
t0 = performance.now();
|
|
hnBigTrieUnserialized.unserialize(selfie);
|
|
const theTrieUnserialized = hnBigTrieUnserialized.createOne(hnBigTrieJS.compileOne(theTrieJS));
|
|
t1 = performance.now();
|
|
stdout('\xA0');
|
|
stdout(
|
|
'HNTrieContainer creation (unserialized) completed in ' +
|
|
(t1 - t0).toFixed(2) + ' ms'
|
|
);
|
|
selfie = undefined;
|
|
|
|
document.getElementById('test').addEventListener('click', ( ) => {
|
|
let parent = document.getElementById('stdout');
|
|
while ( parent.childElementCount !== 0 ) {
|
|
parent.removeChild(parent.firstChild);
|
|
}
|
|
testFlavor(
|
|
hostnamePool,
|
|
'Set (JS)',
|
|
theSet.matches.bind(theSet),
|
|
r => r
|
|
);
|
|
testFlavor(
|
|
hostnamePool,
|
|
'HNTrieContainer (JS)',
|
|
theTrieJS.matchesJS.bind(theTrieJS),
|
|
r => r >= 0
|
|
);
|
|
if ( theTrieWASM !== undefined ) {
|
|
testFlavor(
|
|
hostnamePool,
|
|
'HNTrieContainer (WASM)',
|
|
theTrieWASM.matchesWASM.bind(theTrieWASM),
|
|
r => r >= 0
|
|
);
|
|
}
|
|
testFlavor(
|
|
hostnamePool,
|
|
'HNTrieContainer (unserialized)',
|
|
theTrieUnserialized.matchesJS.bind(theTrieUnserialized),
|
|
r => r >= 0
|
|
);
|
|
});
|
|
});
|
|
|
|
</script>
|
|
</body>
|
|
</html>
|