import argparse import json import sqlite3 import sys import tempfile import time from pathlib import Path from unittest import mock parser = argparse.ArgumentParser() parser.add_argument('project') parser.add_argument('output') parser.add_argument('--rows', type=int, default=500000) args = parser.parse_args() sys.path.insert(0, str(Path(args.project).resolve())) import wxwork_message_browser as browser with tempfile.TemporaryDirectory(prefix='browser-perf-') as directory: root = Path(directory) account = root / 'synthetic' account.mkdir() database = account / 'message.db' with sqlite3.connect(database) as db: db.execute('CREATE TABLE message_table(sender_id TEXT,conversation_id TEXT,content_type INTEGER,send_time INTEGER,content BLOB,server_id TEXT,client_id TEXT)') db.executemany('INSERT INTO message_table VALUES(?,?,?,?,?,?,?)', (('customer', f'M:{index % 2500}', 2, 1700000000 + index, f'synthetic message {index}', str(index), '') for index in range(args.rows))) db.close() original = browser.connect_sqlite queries = [] def connected(*positional, **keywords): db = original(*positional, **keywords) db.set_trace_callback(queries.append) return db report = {'rows': args.rows, 'conversations': 2500, 'project': args.project, 'measurements': []} with mock.patch.object(browser, 'connect_sqlite', side_effect=connected), mock.patch.object(browser, '_refresh_cache', side_effect=AssertionError('Never decrypt during navigation')): for label, options in ( ('cold_open', {}), ('switch_1', {'selected_conversation': 'M:2498'}), ('switch_2', {'selected_conversation': 'M:2497'}), ('switch_3', {'selected_conversation': 'M:2496'}), ('search_old_conversation', {'query': 'M:0'}), ('search_repeat', {'query': 'M:0'}), ): queries.clear() started = time.perf_counter() state = browser.load_browser_snapshot(cache_roots=[root], selected_account='synthetic', conversation_limit=8, message_limit=12, **options) elapsed = time.perf_counter() - started report['measurements'].append({'operation': label, 'seconds': round(elapsed, 6), 'queries': len(queries), 'full_aggregates': sum('COUNT(' in value.upper() or 'GROUP BY' in value.upper() for value in queries), 'result_conversations': len(state['conversations']), 'selected_conversation': state['selectedConversation'], 'error': state['error']}) Path(args.output).write_text(json.dumps(report, ensure_ascii=False, indent=2), encoding='utf-8') print(json.dumps(report, ensure_ascii=False))