Various fine tuning code of recent commits

This commit is contained in:
Raymond Hill 2024-02-28 13:32:24 -05:00
parent 3c299b8632
commit 9862446b10
No known key found for this signature in database
GPG key ID: 25E1490B761470C2
9 changed files with 131 additions and 122 deletions

View file

@ -156,15 +156,6 @@ if ( chrome.storage.sync instanceof Object ) {
}; };
} }
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/session
webext.storage.session = {
clear: ( ) => Promise.resolve(),
get: ( ) => Promise.resolve(),
getBytesInUse: ( ) => Promise.resolve(),
remove: ( ) => Promise.resolve(),
set: ( ) => Promise.resolve(),
};
// https://bugs.chromium.org/p/chromium/issues/detail?id=608854 // https://bugs.chromium.org/p/chromium/issues/detail?id=608854
if ( chrome.tabs.removeCSS instanceof Function ) { if ( chrome.tabs.removeCSS instanceof Function ) {
webext.tabs.removeCSS = promisifyNoFail(chrome.tabs, 'removeCSS'); webext.tabs.removeCSS = promisifyNoFail(chrome.tabs, 'removeCSS');

View file

@ -109,7 +109,7 @@ vAPI.generateSecret = (size = 1) => {
* *
* */ * */
vAPI.sessionStorage = { vAPI.sessionStorage = webext.storage.session || {
get() { get() {
return Promise.resolve({}); return Promise.resolve({});
}, },
@ -122,7 +122,6 @@ vAPI.sessionStorage = {
clear() { clear() {
return Promise.resolve(); return Promise.resolve();
}, },
implemented: false,
}; };
/******************************************************************************* /*******************************************************************************
@ -137,46 +136,21 @@ vAPI.sessionStorage = {
vAPI.storage = { vAPI.storage = {
get(key, ...args) { get(key, ...args) {
if ( vAPI.sessionStorage.implemented !== true ) {
return webext.storage.local.get(key, ...args).catch(reason => { return webext.storage.local.get(key, ...args).catch(reason => {
console.log(reason); console.log(reason);
}); });
}
return vAPI.sessionStorage.get(key, ...args).then(bin => {
const size = Object.keys(bin).length;
if ( size === 1 && typeof key === 'string' && bin[key] === null ) {
return {};
}
if ( size !== 0 ) { return bin; }
return webext.storage.local.get(key, ...args).then(bin => {
if ( bin instanceof Object === false ) { return bin; }
// Mirror empty result as null value in order to prevent
// from falling back to storage.local when there is no need.
const tomirror = Object.assign({}, bin);
if ( typeof key === 'string' && Object.keys(bin).length === 0 ) {
Object.assign(tomirror, { [key]: null });
}
vAPI.sessionStorage.set(tomirror);
return bin;
}).catch(reason => {
console.log(reason);
});
});
}, },
set(...args) { set(...args) {
vAPI.sessionStorage.set(...args);
return webext.storage.local.set(...args).catch(reason => { return webext.storage.local.set(...args).catch(reason => {
console.log(reason); console.log(reason);
}); });
}, },
remove(...args) { remove(...args) {
vAPI.sessionStorage.remove(...args);
return webext.storage.local.remove(...args).catch(reason => { return webext.storage.local.remove(...args).catch(reason => {
console.log(reason); console.log(reason);
}); });
}, },
clear(...args) { clear(...args) {
vAPI.sessionStorage.clear(...args);
return webext.storage.local.clear(...args).catch(reason => { return webext.storage.local.clear(...args).catch(reason => {
console.log(reason); console.log(reason);
}); });

View file

@ -146,7 +146,7 @@ if ( vAPI.webextFlavor.soup.has('firefox') ) {
} }
const µBlock = { // jshint ignore:line const µBlock = { // jshint ignore:line
wakeupReason: '', alarmQueue: [],
userSettingsDefault, userSettingsDefault,
userSettings: Object.assign({}, userSettingsDefault), userSettings: Object.assign({}, userSettingsDefault),

View file

@ -45,18 +45,15 @@ const keysFromGetArg = arg => {
return Object.keys(arg); return Object.keys(arg);
}; };
// Cache API is subject to quota so we will use it only for what is key /*******************************************************************************
// performance-wise *
const shouldCache = bin => { * Extension storage
const out = {}; *
for ( const key of Object.keys(bin) ) { * Always available.
if ( key.startsWith('cache/') ) { *
if ( /^cache\/(compiled|selfie)\//.test(key) === false ) { continue; } * */
}
out[key] = bin[key]; const cacheStorage = (( ) => {
}
return out;
};
const exGet = (api, wanted, outbin) => { const exGet = (api, wanted, outbin) => {
return api.get(wanted).then(inbin => { return api.get(wanted).then(inbin => {
@ -73,22 +70,11 @@ const exGet = (api, wanted, outbin) => {
}); });
}; };
/*******************************************************************************
*
* Extension storage
*
* Always available.
*
* */
const cacheStorage = (( ) => {
const compress = async (bin, key, data) => { const compress = async (bin, key, data) => {
const µbhs = µb.hiddenSettings; const µbhs = µb.hiddenSettings;
const isLarge = typeof data === 'string' &&
data.length >= µbhs.cacheStorageCompressionThreshold;
const after = await scuo.serializeAsync(data, { const after = await scuo.serializeAsync(data, {
compress: isLarge && µbhs.cacheStorageCompression, compress: µbhs.cacheStorageCompression,
compressThreshold: µbhs.cacheStorageCompressionThreshold,
multithreaded: µbhs.cacheStorageMultithread, multithreaded: µbhs.cacheStorageMultithread,
}); });
bin[key] = after; bin[key] = after;
@ -104,7 +90,7 @@ const cacheStorage = (( ) => {
}); });
}; };
return { const api = {
get(argbin) { get(argbin) {
const outbin = {}; const outbin = {};
return exGet(cacheAPI, keysFromGetArg(argbin), outbin).then(wanted => { return exGet(cacheAPI, keysFromGetArg(argbin), outbin).then(wanted => {
@ -152,7 +138,8 @@ const cacheStorage = (( ) => {
promises.push(compress(bin, key, keyvalStore[key])); promises.push(compress(bin, key, keyvalStore[key]));
} }
await Promise.all(promises); await Promise.all(promises);
cacheAPI.set(shouldCache(bin)); memoryStorage.set(bin);
cacheAPI.set(bin);
return extensionStorage.set(bin).catch(reason => { return extensionStorage.set(bin).catch(reason => {
ubolog(reason); ubolog(reason);
}); });
@ -191,17 +178,19 @@ const cacheStorage = (( ) => {
return Promise.all(toMigrate); return Promise.all(toMigrate);
}, },
}; };
})();
// Not all platforms support getBytesInUse // Not all platforms support getBytesInUse
if ( extensionStorage.getBytesInUse instanceof Function ) { if ( extensionStorage.getBytesInUse instanceof Function ) {
cacheStorage.getBytesInUse = function(...args) { api.getBytesInUse = function(...args) {
return extensionStorage.getBytesInUse(...args).catch(reason => { return extensionStorage.getBytesInUse(...args).catch(reason => {
ubolog(reason); ubolog(reason);
}); });
}; };
} }
return api;
})();
/******************************************************************************* /*******************************************************************************
* *
* Cache API * Cache API
@ -234,6 +223,19 @@ const cacheAPI = (( ) => {
const urlToKey = url => const urlToKey = url =>
decodeURIComponent(url.slice(urlPrefix.length)); decodeURIComponent(url.slice(urlPrefix.length));
// Cache API is subject to quota so we will use it only for what is key
// performance-wise
const shouldCache = bin => {
const out = {};
for ( const key of Object.keys(bin) ) {
if ( key.startsWith('cache/' ) ) {
if ( /^cache\/(compiled|selfie)\//.test(key) === false ) { continue; }
}
out[key] = bin[key];
}
if ( Object.keys(out).length !== 0 ) { return out; }
};
const getOne = async key => { const getOne = async key => {
const cache = await cacheStoragePromise; const cache = await cacheStoragePromise;
if ( cache === null ) { return; } if ( cache === null ) { return; }
@ -327,12 +329,13 @@ const cacheAPI = (( ) => {
).catch(( ) => []); ).catch(( ) => []);
}, },
set(keyvalStore) { async set(...args) {
const keys = Object.keys(keyvalStore); const bin = shouldCache(...args);
if ( keys.length === 0 ) { return; } if ( bin === undefined ) { return; }
const keys = Object.keys(bin);
const promises = []; const promises = [];
for ( const key of keys ) { for ( const key of keys ) {
promises.push(setOne(key, keyvalStore[key])); promises.push(setOne(key, bin[key]));
} }
return Promise.all(promises); return Promise.all(promises);
}, },
@ -363,30 +366,46 @@ const cacheAPI = (( ) => {
* *
* */ * */
const memoryStorage = (( ) => { const memoryStorage = (( ) => { // jshint ignore:line
const sessionStorage = webext.storage.session; const sessionStorage = vAPI.sessionStorage;
// This should help speed up loading from suspended state in Firefox for
// Android.
// 20240228 Observation: Slows down loading from suspended state in
// Firefox desktop. Could be different in Firefox for Android.
const shouldCache = bin => {
const out = {};
for ( const key of Object.keys(bin) ) {
if ( key.startsWith('cache/compiled/') ) { continue; }
out[key] = bin[key];
}
if ( Object.keys(out).length !== 0 ) { return out; }
};
return { return {
get(...args) { get(...args) {
return sessionStorage.get(...args).catch(reason => { return sessionStorage.get(...args).then(bin => {
return bin;
}).catch(reason => {
ubolog(reason); ubolog(reason);
}); });
}, },
async keys(regex) { async keys(regex) {
const results = await sessionStorage.get(null).catch(( ) => {}); const bin = await sessionStorage.get(null).catch(( ) => {});
const keys = new Set(results[0]); const keys = [];
const bin = results[1] || {}; for ( const key of Object.keys(bin || {}) ) {
for ( const key of Object.keys(bin) ) {
if ( regex && regex.test(key) === false ) { continue; } if ( regex && regex.test(key) === false ) { continue; }
keys.add(key); keys.push(key);
} }
return keys; return keys;
}, },
async set(...args) { async set(...args) {
return sessionStorage.set(...args).catch(reason => { const bin = shouldCache(...args);
if ( bin === undefined ) { return; }
return sessionStorage.set(bin).catch(reason => {
ubolog(reason); ubolog(reason);
}); });
}, },
@ -522,7 +541,7 @@ const idbStorage = (( ) => {
if ( entry.value instanceof Blob === false ) { return; } if ( entry.value instanceof Blob === false ) { return; }
promises.push(decompress(keyvalStore, key, value)); promises.push(decompress(keyvalStore, key, value));
}).catch(reason => { }).catch(reason => {
ubolog(`cacheStorage.getAllFromDb() failed: ${reason}`); ubolog(`idbStorage.getAllFromDb() failed: ${reason}`);
callback(); callback();
}); });
}; };

View file

@ -72,7 +72,7 @@ const warSecret = typeof vAPI === 'object' && vAPI !== null
: ( ) => ''; : ( ) => '';
const RESOURCES_SELFIE_VERSION = 7; const RESOURCES_SELFIE_VERSION = 7;
const RESOURCES_SELFIE_NAME = 'compiled/redirectEngine/resources'; const RESOURCES_SELFIE_NAME = 'selfie/redirectEngine/resources';
/******************************************************************************/ /******************************************************************************/
/******************************************************************************/ /******************************************************************************/

View file

@ -281,6 +281,12 @@ const isInstanceOf = (o, s) => {
); );
}; };
const shouldCompress = (s, options) =>
options.compress === true && (
options.compressThreshold === undefined ||
options.compressThreshold <= s.length
);
/******************************************************************************* /*******************************************************************************
* *
* A large Uint is always a positive integer (can be zero), assumed to be * A large Uint is always a positive integer (can be zero), assumed to be
@ -1051,10 +1057,9 @@ export const serialize = (data, options = {}) => {
const s = writeBuffer.join(''); const s = writeBuffer.join('');
writeRefs.clear(); writeRefs.clear();
writeBuffer.length = 0; writeBuffer.length = 0;
if ( options.compress !== true ) { return s; } if ( shouldCompress(s, options) === false ) { return s; }
const lz4Util = new LZ4BlockJS(); const lz4Util = new LZ4BlockJS();
const encoder = new TextEncoder(); const uint8ArrayBefore = textEncoder.encode(s);
const uint8ArrayBefore = encoder.encode(s);
const uint8ArrayAfter = lz4Util.encode(uint8ArrayBefore, 0); const uint8ArrayAfter = lz4Util.encode(uint8ArrayBefore, 0);
const lz4 = { const lz4 = {
size: uint8ArrayBefore.length, size: uint8ArrayBefore.length,
@ -1145,7 +1150,6 @@ const THREAD_IAMREADY = 2;
const THREAD_SERIALIZE = 3; const THREAD_SERIALIZE = 3;
const THREAD_DESERIALIZE = 4; const THREAD_DESERIALIZE = 4;
class MainThread { class MainThread {
constructor() { constructor() {
this.name = 'main'; this.name = 'main';

View file

@ -76,6 +76,10 @@ vAPI.app.onShutdown = ( ) => {
permanentSwitches.reset(); permanentSwitches.reset();
}; };
vAPI.alarms.onAlarm.addListener(alarm => {
µb.alarmQueue.push(alarm.name);
});
/******************************************************************************/ /******************************************************************************/
// This is called only once, when everything has been loaded in memory after // This is called only once, when everything has been loaded in memory after
@ -160,6 +164,13 @@ const onVersionReady = async lastVersion => {
await cacheStorage.migrate(µb.hiddenSettings.cacheStorageAPI); await cacheStorage.migrate(µb.hiddenSettings.cacheStorageAPI);
} }
// Remove cache items with obsolete names
if ( lastVersionInt < vAPI.app.intFromVersion('1.56.1b5') ) {
io.remove(`compiled/${µb.pslAssetKey}`);
io.remove('compiled/redirectEngine/resources');
io.remove('selfie/main');
}
// Since built-in resources may have changed since last version, we // Since built-in resources may have changed since last version, we
// force a reload of all resources. // force a reload of all resources.
redirectEngine.invalidateResourcesSelfie(io); redirectEngine.invalidateResourcesSelfie(io);
@ -436,7 +447,7 @@ let selfieIsValid = false;
try { try {
selfieIsValid = await µb.selfieManager.load(); selfieIsValid = await µb.selfieManager.load();
if ( selfieIsValid === true ) { if ( selfieIsValid === true ) {
ubolog(`Selfie ready ${Date.now()-vAPI.T0} ms after launch`); ubolog(`Loaded filtering engine from selfie ${Date.now()-vAPI.T0} ms after launch`);
} }
} catch (ex) { } catch (ex) {
console.trace(ex); console.trace(ex);
@ -506,5 +517,16 @@ ubolog(`All ready ${µb.supportStats.allReadyAfter} after launch`);
µb.isReadyResolve(); µb.isReadyResolve();
// Process alarm queue
while ( µb.alarmQueue.length !== 0 ) {
const what = µb.alarmQueue.shift();
ubolog(`Processing alarm event from suspended state: '${what}'`);
switch ( what ) {
case 'createSelfie':
µb.selfieManager.create();
break;
}
}
// <<<<< end of async/await scope // <<<<< end of async/await scope
})(); })();

View file

@ -4629,6 +4629,7 @@ FilterContainer.prototype.optimize = function(throttle = 0) {
/******************************************************************************/ /******************************************************************************/
FilterContainer.prototype.toSelfie = function() { FilterContainer.prototype.toSelfie = function() {
this.optimize(0);
bidiTrieOptimize(true); bidiTrieOptimize(true);
keyvalStore.setItem('SNFE.origHNTrieContainer.trieDetails', keyvalStore.setItem('SNFE.origHNTrieContainer.trieDetails',
origHNTrieContainer.optimize() origHNTrieContainer.optimize()

View file

@ -1147,7 +1147,10 @@ onBroadcast(msg => {
µb.loadRedirectResources = async function() { µb.loadRedirectResources = async function() {
try { try {
const success = await redirectEngine.resourcesFromSelfie(io); const success = await redirectEngine.resourcesFromSelfie(io);
if ( success === true ) { return true; } if ( success === true ) {
ubolog('Loaded redirect/scriptlets resources from selfie');
return true;
}
const fetcher = (path, options = undefined) => { const fetcher = (path, options = undefined) => {
if ( path.startsWith('/web_accessible_resources/') ) { if ( path.startsWith('/web_accessible_resources/') ) {
@ -1220,8 +1223,11 @@ onBroadcast(msg => {
} }
try { try {
const selfie = await io.fromCache(`compiled/${this.pslAssetKey}`); const selfie = await io.fromCache(`selfie/${this.pslAssetKey}`);
if ( psl.fromSelfie(selfie) ) { return; } if ( psl.fromSelfie(selfie) ) {
ubolog('Loaded PSL from selfie');
return;
}
} catch (reason) { } catch (reason) {
ubolog(reason); ubolog(reason);
} }
@ -1235,7 +1241,8 @@ onBroadcast(msg => {
µb.compilePublicSuffixList = function(content) { µb.compilePublicSuffixList = function(content) {
const psl = publicSuffixList; const psl = publicSuffixList;
psl.parse(content, punycode.toASCII); psl.parse(content, punycode.toASCII);
return io.toCache(`compiled/${this.pslAssetKey}`, psl.toSelfie()); ubolog(`Loaded PSL from ${this.pslAssetKey}`);
return io.toCache(`selfie/${this.pslAssetKey}`, psl.toSelfie());
}; };
/******************************************************************************/ /******************************************************************************/
@ -1255,7 +1262,7 @@ onBroadcast(msg => {
if ( µb.inMemoryFilters.length !== 0 ) { return; } if ( µb.inMemoryFilters.length !== 0 ) { return; }
if ( Object.keys(µb.availableFilterLists).length === 0 ) { return; } if ( Object.keys(µb.availableFilterLists).length === 0 ) { return; }
await Promise.all([ await Promise.all([
io.toCache('selfie/main', { io.toCache('selfie/staticMain', {
magic: µb.systemSettings.selfieMagic, magic: µb.systemSettings.selfieMagic,
availableFilterLists: µb.availableFilterLists, availableFilterLists: µb.availableFilterLists,
}), }),
@ -1268,11 +1275,11 @@ onBroadcast(msg => {
]); ]);
lz4Codec.relinquish(); lz4Codec.relinquish();
µb.selfieIsInvalid = false; µb.selfieIsInvalid = false;
ubolog(`Selfie was created`); ubolog('Filtering engine selfie created');
}; };
const loadMain = async function() { const loadMain = async function() {
const selfie = await io.fromCache('selfie/main'); const selfie = await io.fromCache('selfie/staticMain');
if ( selfie instanceof Object === false ) { return false; } if ( selfie instanceof Object === false ) { return false; }
if ( selfie.magic !== µb.systemSettings.selfieMagic ) { return false; } if ( selfie.magic !== µb.systemSettings.selfieMagic ) { return false; }
if ( selfie.availableFilterLists instanceof Object === false ) { return false; } if ( selfie.availableFilterLists instanceof Object === false ) { return false; }
@ -1300,35 +1307,26 @@ onBroadcast(msg => {
catch (reason) { catch (reason) {
ubolog(reason); ubolog(reason);
} }
ubolog('Selfie not available'); ubolog('Filtering engine selfie not available');
destroy(); destroy();
return false; return false;
}; };
const destroy = function(options = {}) { const destroy = function(options = {}) {
if ( µb.selfieIsInvalid === false ) { if ( µb.selfieIsInvalid === false ) {
io.remove(/^selfie\//, options); io.remove(/^selfie\/static/, options);
µb.selfieIsInvalid = true; µb.selfieIsInvalid = true;
ubolog('Selfie marked for invalidation'); ubolog('Filtering engine selfie marked for invalidation');
}
if ( µb.wakeupReason === 'createSelfie' ) {
µb.wakeupReason = '';
return createTimer.offon({ sec: 27 });
} }
vAPI.alarms.create('createSelfie', { vAPI.alarms.create('createSelfie', {
delayInMinutes: µb.hiddenSettings.selfieAfter delayInMinutes: µb.hiddenSettings.selfieAfter + 0.5
}); });
createTimer.offon({ min: µb.hiddenSettings.selfieAfter }); createTimer.offon({ min: µb.hiddenSettings.selfieAfter });
}; };
const createTimer = vAPI.defer.create(create); const createTimer = vAPI.defer.create(create);
vAPI.alarms.onAlarm.addListener(alarm => { µb.selfieManager = { load, create, destroy };
if ( alarm.name !== 'createSelfie') { return; }
µb.wakeupReason = 'createSelfie';
});
µb.selfieManager = { load, destroy };
} }
/******************************************************************************/ /******************************************************************************/