|
| 1 | +/* tslint:disable no-console */ |
| 2 | + |
| 3 | +import*asBenchmarkfrom'benchmark'; |
| 4 | +import*asosfrom'os'; |
| 5 | +import*asfsfrom'fs'; |
| 6 | + |
| 7 | +exportinterfaceRunner{ |
| 8 | +name:string|((data:unknown)=>string); |
| 9 | +setup:(data:unknown)=>(data:unknown)=>void; |
| 10 | +} |
| 11 | + |
| 12 | +exportinterfacePayload{ |
| 13 | +name:string|((data:unknown)=>string); |
| 14 | +data:unknown; |
| 15 | +} |
| 16 | + |
| 17 | +exportinterfaceIBenchmark{ |
| 18 | +name:string; |
| 19 | +description?:string; |
| 20 | +warmup?:number; |
| 21 | +payloads?:Payload[]; |
| 22 | +test?:(payload:unknown,result:unknown)=>boolean; |
| 23 | +runners:Runner[]; |
| 24 | +} |
| 25 | + |
| 26 | +exporttypePayloadResult=[suite:Benchmark.Suite,payload:Payload,events:Benchmark.Event[]]; |
| 27 | + |
| 28 | +exportconstrunBenchmark=(benchmark:IBenchmark):PayloadResult[]=>{ |
| 29 | +consttitle='Benchmark: '+(benchmark.name||'[unknown benchmark]'); |
| 30 | +console.log('='.repeat(100-title.length-2)+' '+title); |
| 31 | + |
| 32 | +constwarmup=!benchmark.warmup ?'Not specified' :`${benchmark.warmup}x`; |
| 33 | +constversion=process.version; |
| 34 | +constarch=os.arch(); |
| 35 | +constcpu=os.cpus()[0].model; |
| 36 | + |
| 37 | +console.log('Warmup:',warmup,', Node.js:',version,', Arch:',arch,', CPU:',cpu); |
| 38 | + |
| 39 | +constresult:PayloadResult[]=[]; |
| 40 | + |
| 41 | +for(constpayloadofbenchmark.payloads||[{name:'No payload',data:undefined,test:undefined}]){ |
| 42 | +constsuite=newBenchmark.Suite(); |
| 43 | +constdata=payload?.data; |
| 44 | +constname=payload?.name||'[unknown payload]'; |
| 45 | +consttitle=typeofname==='function' ?name(data) :name; |
| 46 | +console.log('-'.repeat(100-title.length-2)+' '+title); |
| 47 | + |
| 48 | +for(construnnerofbenchmark.runners){ |
| 49 | +constfn=runner.setup(data); |
| 50 | +if(benchmark.warmup)for(leti=0;i<benchmark.warmup;i++)fn(data); |
| 51 | +letisCorrect:undefined|boolean=undefined; |
| 52 | +if(benchmark.test){ |
| 53 | +try{ |
| 54 | +isCorrect=benchmark.test(data,fn(data)); |
| 55 | +}catch{ |
| 56 | +isCorrect=false; |
| 57 | +} |
| 58 | +} |
| 59 | +consticon=isCorrect===undefined ?'' :isCorrect ?'👍' :'👎'; |
| 60 | +suite.add((icon ?icon+' ' :'')+(typeofrunner.name==='function' ?runner.name(data) :runner.name),()=> |
| 61 | +fn(data), |
| 62 | +); |
| 63 | +} |
| 64 | + |
| 65 | +constevents:Benchmark.Event[]=[]; |
| 66 | +suite.on('cycle',(event:Benchmark.Event)=>{ |
| 67 | +events.push(event); |
| 68 | +console.log(String(event.target)); |
| 69 | +}); |
| 70 | +suite.on('complete',()=>{ |
| 71 | +console.log(`Fastest is${suite.filter('fastest').map('name')}`); |
| 72 | +}); |
| 73 | +suite.run(); |
| 74 | + |
| 75 | +result.push([suite,payload,events]); |
| 76 | +} |
| 77 | + |
| 78 | +returnresult; |
| 79 | +}; |
| 80 | + |
| 81 | +exportinterfaceIBenchmarkResult{ |
| 82 | +id:number; |
| 83 | +name?:string; |
| 84 | +count:number; |
| 85 | +cycles:number; |
| 86 | +hz:number; |
| 87 | +compiled:(()=>void)|string; |
| 88 | +error:Error; |
| 89 | +fn:(()=>void)|string; |
| 90 | +aborted:boolean; |
| 91 | +running:boolean; |
| 92 | +setup:(()=>void)|string; |
| 93 | +teardown:(()=>void)|string; |
| 94 | +stats:Benchmark.Stats; |
| 95 | +times:Benchmark.Times; |
| 96 | +} |
| 97 | + |
| 98 | +exportconstformatSuite=([suite,payload,events]:PayloadResult):string=>{ |
| 99 | +letstr=''; |
| 100 | +constname=typeofpayload.name==='function' ?payload.name(payload.data) :payload.name; |
| 101 | +str+=`\n## Payload: __${name}__\n`; |
| 102 | +str+='\n'; |
| 103 | +for(consteventofevents){ |
| 104 | +str+=`-${event.target}\n`; |
| 105 | +} |
| 106 | +str+='\n'; |
| 107 | +str+=`Fastest is __${suite.filter('fastest').map('name')}__\n`; |
| 108 | +str+='\n'; |
| 109 | +returnstr; |
| 110 | +}; |
| 111 | + |
| 112 | +exportconstformatSuites=(benchmark:IBenchmark,result:PayloadResult[]):string=>{ |
| 113 | +letstr=''; |
| 114 | +str+=`# Benchmark report: __${benchmark.name}__\n`; |
| 115 | +str+='\n'; |
| 116 | +constwarmup=!benchmark.warmup ?'Not specified' :`${benchmark.warmup}x`; |
| 117 | +constversion=process.version; |
| 118 | +constarch=os.arch(); |
| 119 | +constcpu=os.cpus()[0].model; |
| 120 | +str+=`> Warmup:${warmup}, Node.js:${version}, Arch:${arch}, CPU:${cpu}\n`; |
| 121 | +str+='\n'; |
| 122 | +if(benchmark.description)str+=benchmark.description+'\n'; |
| 123 | +str+='\n'; |
| 124 | +for(constresofresult)str+=formatSuite(res); |
| 125 | +returnstr; |
| 126 | +}; |
| 127 | + |
| 128 | +exportconstrunBenchmarkAndSave=(benchmark:IBenchmark,path:string):void=>{ |
| 129 | +fs.mkdirSync(path,{recursive:true}); |
| 130 | +constresults=runBenchmark(benchmark); |
| 131 | +constmarkdown=formatSuites(benchmark,results); |
| 132 | +fs.writeFileSync(path+`/${benchmark.name.replace(/[^a-z0-9]/gi,'-').toLowerCase()}.md`,markdown); |
| 133 | +}; |