tdweb: optimize start time

GitOrigin-RevId: e98973c0b61a09e74f5eb327080eab63781b5754
This commit is contained in:
Arseny Smirnov 2019-04-12 21:23:17 +03:00
parent 6e05b22a0f
commit af6632390a
2 changed files with 68 additions and 28 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@arseny30/tdweb", "name": "@arseny30/tdweb",
"version": "0.2.36", "version": "0.2.37",
"description": "Javascript interface for TDLib (telegram library)", "description": "Javascript interface for TDLib (telegram library)",
"main": "dist/tdweb.js", "main": "dist/tdweb.js",
"files": [ "files": [

View File

@ -162,38 +162,59 @@ class OutboundFileSystem {
} }
class InboundFileSystem { class InboundFileSystem {
static async create(dbName, root, FS) { static async create(dbName, root, FS_promise) {
let start = performance.now();
try { try {
let ifs = new InboundFileSystem(); let ifs = new InboundFileSystem();
ifs.root = root; ifs.root = root;
ifs.FS = FS;
FS.mkdir(root);
ifs.store = localforage.createInstance({ ifs.store = localforage.createInstance({
name: dbName, name: dbName,
driver: localForageDrivers driver: localForageDrivers
}); });
let keys = await ifs.store.keys();
ifs.pids = new Set(keys); ifs.load_pids();
let FS = await FS_promise;
ifs.FS = FS;
ifs.FS.mkdir(root);
let create_time = (performance.now() - start) / 1000;
log.debug('InboundFileSystem::create ' + create_time);
return ifs; return ifs;
} catch (e) { } catch (e) {
log.error('Failed to init Inbound FileSystem: ', e); log.error('Failed to init Inbound FileSystem: ', e);
} }
} }
async load_pids() {
let keys_start = performance.now();
log.debug('InboundFileSystem::create::keys start');
let keys = await this.store.keys();
let keys_time = (performance.now() - keys_start) / 1000;
log.debug('InboundFileSystem::create::keys ' + keys_time + ' ' + keys.length);
this.pids = new Set(keys);
}
has(pid) { has(pid) {
if (!this.pids) {
return true;
}
return this.pids.has(pid); return this.pids.has(pid);
} }
forget(pid) { forget(pid) {
if (this.pids) {
this.pids.delete(pid); this.pids.delete(pid);
} }
}
async persist(pid, path, arr) { async persist(pid, path, arr) {
try { try {
await this.store.setItem(pid, new Blob([arr])); await this.store.setItem(pid, new Blob([arr]));
if (this.pids) {
this.pids.add(pid); this.pids.add(pid);
}
this.FS.unlink(path); this.FS.unlink(path);
} catch (e) { } catch (e) {
log.error('Failed persist ' + path + ' ', e); log.error('Failed persist ' + path + ' ', e);
@ -202,10 +223,12 @@ class InboundFileSystem {
} }
class DbFileSystem { class DbFileSystem {
static async create(root, FS, readOnly = false) { static async create(root, FS_promise, readOnly = false) {
let start = performance.now();
try { try {
let dbfs = new DbFileSystem(); let dbfs = new DbFileSystem();
dbfs.root = root; dbfs.root = root;
let FS = await FS_promise;
dbfs.FS = FS; dbfs.FS = FS;
dbfs.syncfs_total_time = 0; dbfs.syncfs_total_time = 0;
dbfs.readOnly = readOnly; dbfs.readOnly = readOnly;
@ -221,6 +244,8 @@ class DbFileSystem {
dbfs.syncfsInterval = setInterval(() => { dbfs.syncfsInterval = setInterval(() => {
dbfs.sync(); dbfs.sync();
}, 5000); }, 5000);
let create_time = (performance.now() - start) / 1000;
log.debug('DbFileSystem::create ' + create_time);
return dbfs; return dbfs;
} catch (e) { } catch (e) {
log.error('Failed to init DbFileSystem: ', e); log.error('Failed to init DbFileSystem: ', e);
@ -270,28 +295,35 @@ class DbFileSystem {
} }
class TdFileSystem { class TdFileSystem {
static async create(prefix, FS, readOnly = false) { static async init_fs(prefix, FS_promise) {
let FS = await FS_promise;
FS.mkdir(prefix);
return FS;
}
static async create(prefix, FS_promise, readOnly = false) {
try { try {
let tdfs = new TdFileSystem(); let tdfs = new TdFileSystem();
tdfs.prefix = prefix; tdfs.prefix = prefix;
tdfs.FS = FS; FS_promise = TdFileSystem.init_fs(prefix, FS_promise);
FS.mkdir(prefix);
//WORKERFS. Temporary stores Blobs for outbound files
tdfs.outboundFileSystem = new OutboundFileSystem(
prefix + '/outboundfs',
FS
);
//MEMFS. Store to IDB and delete files as soon as possible //MEMFS. Store to IDB and delete files as soon as possible
let inboundFileSystem = InboundFileSystem.create( let inboundFileSystem = InboundFileSystem.create(
prefix, prefix,
prefix + '/inboundfs', prefix + '/inboundfs',
FS FS_promise
); );
//IDBFS. MEMFS which is flushed to IDB from time to time //IDBFS. MEMFS which is flushed to IDB from time to time
let dbFileSystem = DbFileSystem.create(prefix + '/dbfs', FS, readOnly); let dbFileSystem = DbFileSystem.create(prefix + '/dbfs', FS_promise, readOnly);
let FS = await FS_promise;
tdfs.FS = FS;
//WORKERFS. Temporary stores Blobs for outbound files
tdfs.outboundFileSystem = new OutboundFileSystem(
prefix + '/outboundfs',
tdfs.FS
);
tdfs.inboundFileSystem = await inboundFileSystem; tdfs.inboundFileSystem = await inboundFileSystem;
tdfs.dbFileSystem = await dbFileSystem; tdfs.dbFileSystem = await dbFileSystem;
@ -344,7 +376,7 @@ class TdClient {
if (this.wasInit) { if (this.wasInit) {
return; return;
} }
await this.testLocalForage(); //await this.testLocalForage();
log.setVerbosity(options.jsLogVerbosityLevel); log.setVerbosity(options.jsLogVerbosityLevel);
this.wasInit = true; this.wasInit = true;
@ -355,6 +387,19 @@ class TdClient {
} }
mode = options.mode || mode; mode = options.mode || mode;
var self = this;
let FS_promise = new Promise(resolve => {
self.onFS = resolve;
});
let prefix = options.prefix || 'tdlib';
let tdfs_promise = TdFileSystem.create(
'/' + prefix,
FS_promise,
options.readOnly
);
log.info('load TdModule');
this.TdModule = await loadTdLib(mode); this.TdModule = await loadTdLib(mode);
log.info('got TdModule'); log.info('got TdModule');
this.td_functions = { this.td_functions = {
@ -377,6 +422,7 @@ class TdClient {
}, },
td_get_timeout: this.TdModule.cwrap('td_get_timeout', 'number', []) td_get_timeout: this.TdModule.cwrap('td_get_timeout', 'number', [])
}; };
this.onFS(this.TdModule.FS);
this.FS = this.TdModule.FS; this.FS = this.TdModule.FS;
this.TdModule['websocket']['on']('error', error => { this.TdModule['websocket']['on']('error', error => {
this.scheduleReceiveSoon(); this.scheduleReceiveSoon();
@ -399,7 +445,6 @@ class TdClient {
// wait till it is allowed to start // wait till it is allowed to start
this.callback({ '@type': 'inited' }); this.callback({ '@type': 'inited' });
var self = this;
await new Promise(resolve => { await new Promise(resolve => {
self.onStart = resolve; self.onStart = resolve;
}); });
@ -409,13 +454,8 @@ class TdClient {
if (this.isClosing) { if (this.isClosing) {
return; return;
} }
let prefix = options.prefix || 'tdlib';
log.info('FS start init'); log.info('FS start init');
this.tdfs = await TdFileSystem.create( this.tdfs = await tdfs_promise;
'/' + prefix,
this.FS,
options.readOnly
);
log.info('FS inited'); log.info('FS inited');
// no async initialization after this point // no async initialization after this point