import { log } from '../log'; import { flipArray2D } from '../basic'; import chalk from 'chalk'; import { defaultCompareFn } from '../../algorithm'; interface IAnalyzeResult { name: string; sumTime: number; avgTime: number; callTimes: number; tags: Array<[string, number]>; } const tagMap = new Map(); const state = { analyzing: false, }; function logAnalyzeResults(res: IAnalyzeResult[], options: IAnalyzeOptions) { const cols = [{ key: 'Name' }, { key: 'Avg' }, { key: 'Calls' }]; const tagIndexMap = new Map(); let tagInd = 3; const table = res.map(r => { const u = [r.name, r.avgTime, r.callTimes]; r.tags.forEach(([t, n]) => { if (!tagIndexMap.has(t)) { cols.push({ key: t }); tagIndexMap.set(t, tagInd++); } u[tagIndexMap.get(t)] = chalk.yellow(n); }); return u; }); const W = cols.length; for (let h = 0, H = table.length; h < H; ++h) { for (let w = 3; w < W; ++w) { if (table[h][w] === undefined) { table[h][w] = chalk.grey('-'); } } } log(table, { margin: 1, showColHead: true, cols, showDivider: true, ...(typeof options.sort === 'string' ? { sort: [{ key: options.sort, compareFn: defaultCompareFn }], } : {}), }); } export interface IAnalyzeOptions { sort?: string; } export function analyze any>( fns: F[], cb: (f: F) => void, options: IAnalyzeOptions = {} ) { const results = fns.map(fn => { let sTime = 0; let nCall = 0; tagMap.clear(); cb(((...args: any[]) => { const t = Date.now(); const fnResult = fn(...args); sTime += Date.now() - t; nCall++; return fnResult; }) as F); const result: IAnalyzeResult = { name: fn.name, sumTime: sTime, avgTime: sTime / nCall, callTimes: nCall, tags: Array.from(tagMap.entries()), }; tagMap.clear(); return result; }); logAnalyzeResults(results, options); } analyze.tag = (name: string) => { tagMap.set(name, (tagMap.get(name) || 0) + 1); return true; };